前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django路由系统学习(四)

Django路由系统学习(四)

作者头像
无涯WuYa
发布2018-10-25 16:09:39
4660
发布2018-10-25 16:09:39
举报

Django的执行原理中已经学习了django的执行过程,本小节重点来介绍django的路由系统,也就是url的部分,在前面的Django的执行原理中,我们写了一个Hello World的实例,来演示django的第一个实例,这里来再次看下项目的目录结构,见截图:

在webSite的项目下,有blog的app的应用,第一个实例的函数写在了blog下的views.py的文件中,它的url是在webSite下的urls.py文件中,见urls.py的源码:

代码语言:javascript
复制
#!/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的源码:

代码语言:javascript
复制
#!/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地址,见源码:

代码语言:javascript
复制
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启动服务后,在浏览器中输入:

http://127.0.0.1:8000/login/

http://127.0.0.1:8000/logout/

就可以访问到对应的login与logout的函数,这里不在截图了。

这里,我们来再次看urls.py的文件源码,可以看到,我们在views.py文件中编写一个函数后,需要在urls.py增加该函数的访问url,如url(r'^login/$', login),该url它有什么含义了,具体为:在url中包含了正则表达式^与$,^是含义是要求对字符串的头部进行匹配,$表示对字符串的尾部进行匹配,如果没有了^和$符号会怎么样了?我们可以来实战看看,就login的url,取消^与$,见取消后的源码:

代码语言:javascript
复制
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文件,见重构后的源码

代码语言:javascript
复制
#!/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文件进行重够,见源码

代码语言:javascript
复制
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的源码

代码语言:javascript
复制
#!/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的源码

代码语言:javascript
复制
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,见重构的结果:

代码语言:javascript
复制
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的文件源码:

代码语言:javascript
复制
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文件,见源码

代码语言:javascript
复制
#!/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,凡是不可能完美。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档