Django中路由的作用
URL配置(URLconf)就是Django 所支撑的网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行
典型例子:
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
路由的基本使用
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
- 正则表达式:一个正则表达式字符串
- views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 参数:可选的要传递给视图函数的默认参数(字典形式)
- 别名:一个可选的name参数
注意:
- 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的’r’ 是可选的但是建议加上。它告诉Python 这个字符串是“原始的”
- urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续
APPEND_SLASH
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加’/’。
其效果就是:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
]
访问 http://www.example.com/blog 时,默认将网址自动转换为 http://www.example/com/blog/ 。
如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求 http://www.example.com/blog 时不再向后面自动添加/,就会提示找不到页面。
路由的分组
无名分组
# 路由层
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
]
# 视图层
def year_archive(request, year):
'''
year: 接收路由层传递过来的参数
'''
return HttpResponse('当前是%s年' % year)
上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。
无名分组分出几个值,视图函数就要接受几个值(位置参数形式传过来的)
有名分组
在Python 正则表达式中,命名正则表达式组的语法是(?Ppattern),其中name 是组的名称,pattern 是要匹配的模式。
按照有名分组,上面的示例应该这样写:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]
有名分组与无名分组在使用上没有太大差别,只是有名分组对应的视图函数的形参名字必须和分组名保持一致,也就是说,有名分组会把分出来的参数按照关键字参数传递给视图函数,所以一定要保持名字上的一致
在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价。
注意:有名分组和无名分组不能混合使用
路由分发
一个Django项目里面有多个app时,不同app的视图层可能会有名字相同的视图函数,为了避免名称冲突,我们通过路由分发的方式在总路由中进行分发,使每个app在自身内部进行路由的配置
# 导入include
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 匹配顺序:匹配app01成功则相应include函数,去到app01文件夹下的urls文件中继续匹配后续路由
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls'))
]
# app01中的urls文件内容
from app01 import views
urlpatterns = [
url(r'^test/', views.test),
]
如果浏览器输入app01/test/,就会响应到app01下views中的test取执行
反向解析(了解)
在视图函数中重定向的地址如果是写死的,url地址变更时,需要所有的url都进行修改,比较麻烦,我们可以通过反向解析,动态获取url的地址
# 路由层
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/$', views.test, name='test')
]
# 视图层
from django.shortcuts import reverse
def re_url():
url=reverse('test(url地址的别名)')
# 如果做了分组(意味着需要接受参数)
url=reverse('test(url地址的别名)',args=[],kwargs={})
return redirect(url)
{# django模板层 #}
{% url 'url地址的别名'%}
# 如果做了分组(意味着需要接受参数)
{% url 'url地址的别名' 参数1 参数2 ... 参数n %}
这样,即使路由层中的路由更改了,我们也可以不用修改视图层或模板层的路由地址,即便我们不应该去修改路由层中的路由。
名称空间
路由分发时,可以指定名称空间:
# 导入include
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls', namespace='app01')),
url(r'^app02/', include('app02.urls', namespace='app02'))
]
名称空间可以在视图层进行反向解析使用
不建议使用名称空间