17 路由匹配、无名有名分组、反向解析、无名有名解析、路由分发
一、路由匹配
基本格式:
url(正则表达式,函数或者类型地址)
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
参数说明:
正则表达式:一个正则表达式字符串
views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
参数:可选的要传递给视图函数的默认参数(字典形式)
别名:一个可选的name参数
路由匹配的原则:从上往下正则表达式能够匹配到内容就算匹配成功会立刻执行后面的视图函数并且结束整个路由匹配过程
在路由匹配环节如果第一次都没有匹配上django会在路径后面加斜杠再次匹配
APPEND_SLASH = True # 改参数可以控制 建议使用默认的自动添加(系统默认是True,匹配不到就加斜杠再次匹配)
APPEND_SLASH = False #取消自动加斜杠
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首页
url(r'^$',views.home),
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
# 404页面
url(r'',views.error)
]
二、django之无名有名分组
1.无名分组
分组:就是给某一段 正则表达式 用小括号扩起来
url(r'^test/([0-9]{4})/',views.test) # test(request,1234)
def test(request,xx):
print(xx)
return HttpResponse('test')
在路由匹配如果将某部分正则使用括号括起来了
无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
2.有名分组(可以给正则表达式起一个别名)
url(r'^testadd/(?P<year>[0-9]{4})',views.testadd) # testadd(request,year=1234)
def testadd(request,year):
print(year)
return HttpResponse('testadd')
在路由匹配如果将某部分正则使用括号括起来了
那么该部分正则匹配到的内容会当做关键字参数传递给后面的视图函数
3.无名有名能否混用?(不能混用)
url(r'^index/(\d+)/(?P<year>\d+)/',views.index)
def index(request,args,year):
print(args,year)
return HttpResponse("index")
4.同一个分组可以用N次
# 单个的分组可以使用多次
url(r'index/(\d+)/(\d+)/(\d+)/', views.index),
url(r'index1/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/', views.index1),
def index(request,*args):
print(args)
return HttpResponse('test')
def index1(request, **kwargs):
print(kwargs)
return HttpResponse('test')
三、反向解析
通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数
通过标记解析出一个结果 该结果可以访问到标记所在的那一行地址
1.在路由层书写正则与函数名的时候 在后面加一个唯一标识(起别名)
url('home/', views.home,name='home'),
# 反向解析
# 后端反向解析(需要导入reverse模块)
from django.shortcuts import render,HttpResponse,redirect,reverse
def home(request):
print(reverse('home'))
return render(request, 'home.html')
# 前端反向解析
<a href="{% url 'home'%}">111</a>
此时,你输入
url('home111/', views.home,name='home'),则前后端方向解析出来的就是home111
四、无名有名的反向解析
1.无名分组的反向解析(url需要起别名,前后端需要传参数)
# urls.py
url('home/', views.home,name='home'),
url(r'test/(\d+)/', views.test,name='test'),
# 前端
<a href="{% url 'test' 111 %}">111</a>
# 后端
def home(request):
print(reverse('test',args=(111,)))
return render(request,'home.html')
这个数字写代码的时候应该什么?
数字一般情况下放的是数据的主键值 数据的编辑和删除
url(r'^edit/(\d+)/',views.edit,name='xxx') def edit(request,edit_id): reverse('xxx',args=(edit_id,)) {%for user_obj in user_queryset%} <a href="{% url 'xxx' user_obj.id %}">编辑</a> {%endfor%}
2.有名分组的反向解析
# urls.py
url('home/', views.home,name='home'),
url(r'test/(?P<year>\d+)/', views.test,name='test'),
# 前端
<a href="{% url 'test' year=123 %}">111</a>
<a href="{% url 'test' 123 %}">222</a> #简写
# 后端
def home(request):
print(reverse('test', kwargs={'year':111}))
print(reverse('test',args=(111,))) #简写
return render(request,'home.html')
五、路由分发
当django项目特别庞大的时候 如果所有的路由匹配都写在项目的总路由中会导致总路由过于复杂不利于维护 此时可以将路由做拆分 """ django支持所有的应用都可以拥有自己的 urls.py templates文件夹 static文件夹 也就意味着多人协同开发变得更加的简单了 """ 如何将多个单独的app组织到一起 >>> 路由分发 总路由 from app01 import urls as app01_urls from app02 import urls as app02_urls from django.conf.urls import url,include # 路由分发 url(r'^app01/',include(app01_urls)), #直接从app01找 url(r'^app02/',include(app02_urls)), 子路由 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] 子路由 from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index) ] #总路由更加简便的写法(^app01不要以$结尾)
不需要从app01,app02导数据
urlpatterns = [
url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')),]