/ 2018-12-07
用户从浏览器发出的请求会首先打到django url的路由分发系统这里,然后再到views视图--》models模型--》template模板--》用户浏览器,urls.py 文件主载着你整个网站的所有页面&接口的url分配。
正式开讲django的路由语法前,先要知道路由分为以下两种:
静态路由:已经明确定义好的一条路由,比如下例,用户只能在浏览器上输入/articles/2003/ 才能匹配到这条路由,输入任何其它的都匹配不上本条。
urlpatterns = [ path('articles/2003/', views.special_case_2003), ]
动态路由:定义的只是路由规则,比如只能输入数字、或特定排列、长度的字符等,你不知道用户会具体输入什么,只要符合你的规则即可。
Django urls.py 配置
Django 的路由本质上是通过正则表达式来对用户请求的url进行匹配
from django.urls import re_path from app01 import views urlpatterns = [ re_path(r'articles/2003/$', views.special_case_2003), # 静态路由 re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), # 动态路由 re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), # 动态路由 re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail), # 动态路由 ]
以上路由对应views.py视图方法
def special_case_2003(request): return HttpResponse("dddd") def year_archive(request,year): return HttpResponse("year_archive" + str(year)) def month_archive(request,year,month): return HttpResponse("month_archive %s-%s" %(year,month)) def article_detail(request,year,month,slug): return HttpResponse("article_detail %s-%s %s" %(year,month,slug))
虽然实现了路由匹配,但url中的代码看着很笨拙+丑陋,不过在黑暗的django
1.0时代,大家只能这么玩。不过解放之神django2.0来啦,带来了路由匹配新玩法。
from django.urls import path from . import views 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), ]
先说,实现的功能跟之前用re写的路由一样,但是直观来看,是不是干净了很多?
系统默认自带的converter已经可以满足你大部分的url匹配需求,但有特殊情况不能满足时,你还可以自定义converter。
自定义Path Converter
class FourDigitYearConverter: regex = '[0-9]{4}' def to_python(self, value): return int(value) def to_url(self, value): return '%04d' % value
通过上面的regex参数来看, 其实django 2.0 这个path
converter本质上也只是通过对正则表达式进行了封装,使其调用更简单而已。
include 子url
当有多个app时,每个app可以有自己的urls.py, 只需在顶级urls.py中include一下就可以!
from django.urls import include, path urlpatterns = [ # ... snip ... path('community/', include('aggregator.urls')), path('contact/', include('contact.urls')), # ... snip ... ]
django 在匹配url时,只要遇到include()语法, 就会把url分成2部分,比如上面代码里的url,
只要匹配上community/,就会把整条url丢给include('aggregator.urls')子urls.py。
子urls.py负责匹配后面的部分。
减少重复的url
如果url 中出向很多重复的部分,可以按下面的方法聚合:
from django.urls import include, path from apps.main import views as main_views from credit import views as credit_views extra_patterns = [ path('reports/', credit_views.report), path('reports/<int:id>/', credit_views.report), path('charge/', credit_views.charge), ] urlpatterns = [ path('', main_views.homepage), path('help/', include('apps.help.urls')), path('credit/', include(extra_patterns)), ]
传递额外参数给views
from django.urls import path from . import views urlpatterns = [ path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}), ]
*注:这个功能很少用,知道就行了。
到此,我们就掌握了django url系统的大部分用法,是不是很简单?
(2)