路由层
目录
-
django请求生命周期流程图
-
路由层相关知识
内容
django请求生命周期流程图
整体概括请求的走向以及django的核心组成部分
路由匹配
路由匹配的特点
只要匹配上了就会立刻结束执行对应的视图函数,并且url方法的第一个参数其实是一个正则表达式,只要正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了
正则是test 内容是test 那么可以匹配出test文本
正则是test 内容是testadd 那么还可以匹配出test文本
django二次追加斜杠机制
正则是test/,内容是test,那么首次无法匹配,首次匹配不上 那么django还会让浏览器默认加斜杠再次发送请求
首次是test 301,第二次就是test/ 200
斜杠机制可以取消,但是不推荐
APPEND_SLASH = False
解决路由前面可以随意乱写的问题
正则是test/,内容是abcdefgtest/,那么可以匹配出文本test
可以在正则的最前面加上上箭头来限制
解决路由后面可以随意乱写的问题
正则是^test/,内容是test/abc/edf/acd/,那么可以匹配出文本test
可以在正则的最后面加上$来限制
由于第一个参数是正则,所以当项目特别大,对应关系特别多的时候要格外的注意是否会出现路由顶替的现象
定制一个主页面
用户不携带后缀可以直接访问
url(r'^$',views.home)
定义一个尾页
用户输入一个没有对应关系的直接返回
url(r'.*',views.error)
无名有名分组
无名分组
url(r'^test/([0-9]{4})/$', views.test)
路由匹配成功之后就会调用视图函数默认情况下会自动给视图函数传递一个request位置参数
test(request)
如果路由匹配中使用括号对正则表达式进行了分组,那么在调用视图函数的时候会将括号内匹配到的内容当做位置参数传递给视图函数
test(request,括号内正则表达式匹配到的内容)
有名分组
url(r'^testadd/(?P<user_id>[0-9]{4})$', views.testadd)
给括号内的正则表达式起别名之后,匹配成功则会讲括号内匹配到的内容按照关键字参数传递给视图函数
testadd(request,user_id=括号内正则表达式匹配到的内容)
无名有名分组不能混合使用,单个可以重复使用
反向解析
补充
a标签的href可以写网址的全称,也可以写后缀 href='https://www.baidu.com' href='/login/'(自动补全当前服务的ip和port)
反向解析
页面上有很多a标签链接了其他路由,路由匹配表达式出现了变化,html页面上的地址全部失效
通过反向解析可以获取到一个结果 该结果可以访问到一个路由
步骤1:给对应关系起别名
url(r'^func666/',views.func,name='func_view')
步骤2:使用反向解析获取结果
前端:{% url 'func_view' %}
后端:from django.shortcuts import reverse reverse('func_view')
无名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
无法明确括号内正则表达式的内容 需要人为指定
前端:{% url 'func_view' 123 %}
后端: from django.shortcuts import reverse reverse('func_view',args=(666,))
有名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(?P<id>\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
无法明确括号内正则表达式的内容 需要人为指定
前端:{% url 'func_view' 123 %} ;{% url 'func_view' id=123 %}
后端: from django.shortcuts import reverse reverse('func_view',args=(666,)) reverse('func_view',kwargs={'id':1}) 无名有名反向解析中的手动传值,这个值在实际工作中可以是数据的主键值、页面的页码、区域的编号等
路由分发
如果一个django项目特别庞大,里面有很多应用,每个应用下有很多对应关系 ,那么django自带的路由层里面的代码就会非常非常的多,如何优化?
根据应用的不同拆分到不同的应用中,django支持每个应用都可以有自己独立的路由层、模板层、静态文件、视图层(默认)、模型层(默认) 上述特性能够让django在分组开发上更加的方便快捷,所有人都可以在应用中开发完整的项目功能,最后汇总到一个空的django项目中,然后通过路由分发整合所有人的应用
1.创建多个应用,并去配置文件中注册
INSTALLED_APPS = [ 'app01', 'app02' ]
2.在多个应用中编写相同的路由
urlpatterns = [
url(r'^index/',views.index111) ] urlpatterns = [ url(r'^index/',views.index) ]
3.路由分发
总路由
from django.conf.urls import url, include from app01 import urls as app01_urls from app02 import urls as app02_urls url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls))
总路由只负责分发 不负责视图函数对应
上述代码还可以简写
from django.conf.urls import url, include url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls'))
如果多个应用下业务逻辑代码很多,导致views.py内代码繁重
我们可以将views.py移除,换成views文件夹,然后在该文件夹内根据业务逻辑的不同拆分成不同的py文件
总路由结尾一定不能加$符,否则无法分发
名称空间
默认情况下反向解析是不会自动识别应用前缀的,如何解决反向解析问题
方式1:名称空间
总路由添加名称空间 url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02'))应用反向解析自动提示 reverse('app01:index_view') reverse('app02:index_view') {% url 'app01:index_view' %} {% url 'app02:index_view' %}
方式2:只需要确保反向解析的别名在整个项目中不重复即可
可以在别名的前面加上应用名的前缀 url(r'^index/',views.index,name='app01_index_view')