在Django的执行原理中已经学习了django的执行过程,本小节重点来介绍django的路由系统,也就是url的部分,在前面的Django的执行原理中,我们写了一个Hello World的实例,来演示django的第一个实例,这里来再次看下项目的目录结构,见截图:
在webSite的项目下,有blog的app的应用,第一个实例的函数写在了blog下的views.py的文件中,它的url是在webSite下的urls.py文件中,见urls.py的源码:
#!/usr/bin/env python
#coding:utf-8
"""webSite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include,patterns
from django.contrib import admin
from blog.views import *
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/$', index),
]
在这里我们可以看到,访问的url实际上写在了urls.py的文件中,那么我们再次在views.py文件中编写登录,退出的函数并且访问,见views.py的源码:
#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse('<center><h3>Hello World</h3></center>')
def login(requets):
return HttpResponse('login')
def logout(request):
return HttpResponse('logout')
更新urls.py的文件,加入访问login与logout函数的url地址,见源码:
from django.conf.urls import url,include,patterns
from django.contrib import admin
from blog.views import *
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
]
执行命令python manage.py runserver启动服务后,在浏览器中输入:
就可以访问到对应的login与logout的函数,这里不在截图了。
这里,我们来再次看urls.py的文件源码,可以看到,我们在views.py文件中编写一个函数后,需要在urls.py增加该函数的访问url,如url(r'^login/$', login),该url它有什么含义了,具体为:在url中包含了正则表达式^与$,^是含义是要求对字符串的头部进行匹配,$表示对字符串的尾部进行匹配,如果没有了^和$符号会怎么样了?我们可以来实战看看,就login的url,取消^与$,见取消后的源码:
from django.conf.urls import url,include,patterns
from django.contrib import admin
from blog.views import *
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/$', index), url(r'login/', login),
url(r'^logout/$', logout),
]
再次对login的函数进行访问,见访问的截图:
看如上的截图,我们发现取消了^与$字符串后,不管是前面还是后面,访问地址很随意的,这样的效果的确不是我们可以看到的,加上^与$字符串后,我们再来看访问的截图,看看结果是什么,见截图:
可以看到,加上^与$字符串后,再次访问页面提示404,这就是我们想要的效果,到这里也就明白在url中,^与$字符串的含义不仅仅是因为它是正则表达式,更多的是限制了访问的url开头和结束,防止某些认为的恶意攻击。django框架中,关于正则表达式的介绍,见链接地址http://www.djangoproject.com/r/python/re-module/,见截图:
在一个django的项目中,一般有很多的app的应用的,一般怎么来区分某个url是那个应用的,备注可以解决,但是备注仅仅是一个提示,比如有二个app的,都有函数index,那么它的url如果都是index,那么访问的到底是A的了还是B的了, 答案是不知道的,确实无法知晓,但是我们可以通过分发来解决该问题的,什么是分发,也就是说,url访问到项目的URL后,再分发到各个APP的URL,各个APP的urls.py文件具体实现要显示的url,这样就解决了刚才说的二个应用,都有一个index的函数,url都是index的问题,下面就来实现这个过程,实现的步骤为:
1、把webSite项目下的urls.py文件复制到blog的app下
2、重构webSite项目下的urls.py文件,见重构后的源码
#!/usr/bin/env python#coding:utf-8
from django.conf.urls import url,include,patterns
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/',include('blog.urls',namespace='blog')),
]
3、把blog下的urls.py文件进行重够,见源码
from django.conf.urls import url,include,patterns
from .views import *
urlpatterns = [
url(r'^index/$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
]
4、启用再次访问login的链接,见地址:
访问地址是http://127.0.0.1:8000/blog/login/,可以看到,这样我们就可以依据访问的url可以知道,访问的地址是来自哪个app的那个链接的,而不需要通过备注等其他的什么。
在views.py的函数中,函数某些时候都是有参数的,很多的时候,我们不可能只写一个函数而没有参数,包括对url的访问,后面都是带了参数的,下面就以具体的案例来说明参数在url中的实际应用,编写函数,见views.py的源码
#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse('<center><h3>Hello World</h3></center>')
def login(requets):
return HttpResponse('login')
def logout(request):
return HttpResponse('logout')
def list(request,id,name):
return HttpResponse('ID is %s,name is %s'%(id,name))
编写新的函数list,该函数带了二个参数,分别是id和name,编写它的url,见urls.py的源码
from django.conf.urls import url,include,patterns
from .views import *
urlpatterns = [
url(r'^index/$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
url(r'^list/(\d*)/(\D*)/$',list),
]
访问的时候,带上参数,如访问地址http://127.0.0.1:8000/blog/list/2/django/ ,见结果截图:
依据截图来看,可以看到达到我们的期望,函数list第一个参数是id,第二个参数是name,url的链接中也是依据这个顺序而来的,事实上,我们可以使用url的模板来再次重构list函数的url,见重构的结果:
from django.conf.urls import url,include,patterns
from .views import *
urlpatterns = [
url(r'^index/$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
url(r'^list/(?P<id>\d*)/(?P<name>\D*)/$',list),]
见重构的url,这样比较更加规范点,我们就可以知道,使用url访问的时候,第一个参数是指的是id,第二个参数指的是name,使用http://127.0.0.1:8000/blog/list/2/django/ 。那么在一个list函数中,或者说在url访问list函数中,它的参数可以默认吗?答案是可以的,比如名字默认是“wuya”,这里需要再次重构下url,见重构后的url的文件源码:
from django.conf.urls import url,include,patterns
from .views import *
urlpatterns = [
url(r'^index/$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
url(r'^list/(?P<id>\d*)/$',list,{'name':'wuya'}),
]
在url中可以看到,名字默认是wuya,访问看看http://127.0.0.1:8000/blog/list/2/,默认输出的是否是wuya,见截图:
可以看到,果然是我们设置的wuya。
在前面介绍过,一个django的项目,可以有多个app的应用,截至目前,我们的项目app应用只有一个那就是blog,我们在创建一个app的应用,名称为app,见创建的命令:
通过截图可以看到,在项目中已经创建了app的应用app,把创建的app应用加入到配置文件中,并在app的函数中编写index的函数并访问,这里不在描述这么写,如果不清楚,建议再次看该文章的前面部分。看结果截图:
看到这里,不知道发现一个问题吗?那就是当一个django项目里面有很多的app的时候,每个app里面都得有一个urls.py文件,如果么个app的函数名字修改,就得到那个app下的urls.py文件里面去维护,这实在是麻烦,python的追求是简单而优雅,那么通过什么方式来实现,在一个文件里面来进行维护了?实现的方式如下:
1、删除每个app里面的urls..py文件
2、只维护项目下的urls.py文件,见源码
#!/usr/bin/env python
#coding:utf-8
from django.conf.urls import url,include,patterns
from django.contrib import admin
urlpatterns = patterns(
url(r'^admin/', admin.site.urls),
)
urlpatterns+=patterns( 'blog.views',
url(r'^index/$', 'index'),
url(r'^login/$', 'login'),
url(r'^logout/$', 'logout'),
url(r'^list/(?P<id>\d*)/$', 'list', {'name': 'wuya'}),
)
urlpatterns+=patterns( 'app.urls',
url(r'^index/$', 'index'),
)
OK,这样就可以实现在一个文件里面维护所有的url了,但是有一个缺点,就是当二个app的都有一个同名的函数,并且url名字一样,是按顺序访问的,如上面的,blog与app里面都有index的url,访问的时候访问的是blog的index,关于这个,建议既然是不同的app,函数名称就不要一样,当然还有url,凡是不可能完美。