1、Django路由的本质是URL与URL所对应的视图函数之间的映射表。在请求过来的时候,通过匹配URL去执行对应的视图函数。如图:
2、URL路由的基本格式
#django1系列版本中 from django.conf.urls import url urlpatternes = [ url('正则表达式','views视图函数', '参数','别名') ] #如果在django2.0版本中就会发生变化 from django.urls import path urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), ] #2.0中不再使用url,而是用path代替
正则表达式:一个正则表达式字符串,用来匹配url
views视图函数:一个可调用的对象,通常为一个视图函数,或者视图函数所指定的路径。例如,为了提高代码的可维护性,在总的url中,指定了某一个app下所对应的url路径,这样改动的时候只需要对总的Django项目下的url做修改就可以。
参数:传给视图函数的默认参数(字典形式)
别名:用name起的一个别名,当用reverse的时候,即反向解析url时会用到。也可以提高代码的维护性。
3、如何理解URL中的正则表达式
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
注意事项:
1、正则匹配从urlpatternes中从上到下逐一匹配,一旦匹配成功将不再乡下匹配。
2、如果想要拿到URL中的某个值,只需要在其周围用括号括起来。这样就可以将html文件中的用?拼接的路径直接写在url中了。
3、不需要添加前导的反斜杠,因为每个url都会有,例如是'^articles'而不是'/articles'。
4、正则前边的r是可选的,但是最好加上,防止转义。
5、就以第一条url为例,以'/'结尾,但是不写'/'也能跳转到该页面,那是因为在Django中默认将APPEND_SLASH = True,其作用就是在末尾追加'/',所以即使不加'/'也能跳转,所以在settings.py文件中改成APPEND_SLASH = False时就可以解决这个问题。
url(r'^articles/2003/$', views.special_case_2003),
4、命名分组,就是在分组前面加?P<命名名称>,并将这个命名分组的整体用圆括号括起来。此时,views视图函数中的参数就必须是命名名称或者**kwargs。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
1、命名分组和分组的区别在于,分组传参是传的位置参数,而命名分组传的是关键字参数。
2、当使用分组或命名分组的时候,views视图函数中需要加对应数量的参数,有几个括号,视图函数中传几个参数。
3、捕捉到的参数永远都是字符串
5、视图函数中设定默认值
# urls.py中 from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), #没有获取值 url(r'^blog/page(?P<num>[0-9]+)/$', views.page), #命名分组获取值 ] # views.py中,可以为num指定默认值 def page(request, num="1"): pass
此时,如果第一个url匹配上了,此时就会使用默认值num=1,如果第二个匹配上了,就会使用传的num的值。
6、命名URL和反向解析URL
命名URL实际上就是给URL的这条匹配路径起一个别名,用这个别名去代替这个路径。
URL的反向解析就是通过别名能够真实的解析到真正的路径进行网页的跳转。
反向解析的写法:
1、如果在模板中也就是(html文件中),就需要将需要跳转的路径写成{% url '别名' %}
2、如果在views视图函数中,遇到页面跳转的路径时,就要写成 reverse('别名', 参数),如果用了分组匹配取值,就需要传参数。
# URL的命名 url(r'^home', views.home, name='home'), # 给我的url匹配模式起名为 home url(r'^index/(d*)', views.index, name='index'), # 给我的url匹配模式起名为index
#在模板中的使用方法 {% url 'home' %} #在views视图函数中的使用方法 from django.urls import reverse return redirect(reverse('index' ,参数))
7、命名空间
当一个Django项目中,有多个app时,如图
通过路由分发将总的路由区分开,也就是说将对应的url写在对应的url中。通过include
from django.conf.urls import url, include urlpatterns = [ url(r'^app03/', include("app03.urls")), url(r'^app02/', include("app02.urls")), ]
然后app中的urls中的url路由如果有别名起的相同的,在反向解析的时候就会出现后者把前者覆盖的现象,使得解析混淆。如图
# app02的urls from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^home/$', views.student_list, name='home') #name相同 ] # app03的urls from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^home/$', views.student_list, name='home') #name相同 ]
此时就需要 命名空间来对该url进行一个命名用到namespace='app名字',如图
from django.conf.urls import url, include urlpatterns = [ url(r'^app02/', include('app02.urls', namespace='app01')), url(r'^app03/', include('app03.urls', namespace='app02')), ]
如何调用呢?如图
#在模板中使用 {% url 'app01:home' %} #在views视图函数中使用 v = reverse('app01:home')
这样即使重名,也可以通过namespace命名的名称,找到对应的url。