django中的路由层
1.什么是路由层
简单来说,就是通过路由层中的path函数,告诉django遇到那个url,执行那个视图函数
2.路由层的请求流程
1.客户在浏览器输入网址→请求进入django的setting.py中的ROOT_URLCONF寻找指定使用的urls.py文件位置(如果中间件有路由功能,urls文件功能会被其替代)
2.Django会先匹配项目目录下的path路径然后在匹配应用里面的url路径,从上至下查找url匹配,一旦匹配成功,停止查找。
3.一旦匹配url成功后,路由层向视图层传递下列参数:
1)一个HttpRequest实例,即request
2)如果url中的可变参数没有命名,那么就按照位置来与视图函数中的形参一一对应,如果有则按关键字方式传参
4.如果匹配不到url,Django会发出异常
re_path(r"^test/$",views.test)
注意:path路径匹配是会自动在url后面加上一个斜杠,即先匹配test没有找到,会自动加个/在匹配一次!
如何取消自动加斜杠?
在setting.py里添加APPEND_SLASH = False 默认是True
3.路由层的格式和参数说明
3.1有名分组和无名分组
分组:就是给某一段正则表达式用小括号扩起来
无名分组:就是将括号内的正则表达式匹配到的内容当做位置参数传递给后面的视图函数
from django.urls import path, re_path
re_path(r"^test/(d+)/",views.test)
def test(request,xx): # xx这个参数就是对应path里面的(d+)
pass
有名分组:可以给正则表达式起个别名
from django.urls import path, re_path
re_path(r‘^(?P<自定义参数名>正则表达式)/$",view.xxx,name),
def test(request,自定义参数名):
pass
有名无名不能混用!单个分组可以使用多次!
3.2url反向解析
反向解析的步骤:
# 1.先给改url起一个别名
re_path(r"^test/$",views.test,name="ooo")
# 2.后端反向解析(视图层)
先导入reverse
from django.shortcuts import reverse
print(reverse(‘ooo’)) # 得到的就是对应别名的url
# 3.前端反向解析
在需要url的地方,改成如下格式:
<a href="{% url "ooo" %}">111</a>
3.3有名无名的反向解析
1.无名分组
后端部分:
先导入reverse
from django.shortcuts import reverse
print(reverse(‘ooo’),args=(1,))#需要传一个对应参数args,里面的1可以配正则表达式匹配到
前端部分:
<a href="{% url "ooo" 123 %}">111</a>
# 123是匹配到url的正则表达式
2.有名分组
其实是和无名分组一样的,但是也可以写成关键字方式传参
print(reverse(‘ooo’),kwargs={‘year’:1111}))
<a href="{% url "ooo" year=1111a>
传入的数字参数一般是数据的主键值!!
3.4路由分发
起因:分布式路由是基于django应用诞生的,有了应用则就应该有分布式路由,主路由不用在处理用户具体路由了,而是转而做请求的分发,具体的请求由各自的应用负责。
主路由语法:
from django.urls import path,include
# 匹配http://127.0.0.1:8000/music/index--music应用path("music/", include("music.urls"))
include("app名字.url模块名")
作用是将当前path里面music路由转到include里面的这个应用路由里处理
子路由语法:
手动创建一个urls.py,结构和主路由完全一样
只是path后面的第一个参数,只需管主路由path匹配的后面一部分
3.5名称空间
在各路由起别名的时候,由于我们采用的是分布式路由开发,很有可能每个开发人员起的别名是一样的,这样我们在进行反向解析的时候就没有用了!
因此,名称空间的使用很好的解决了这一问题!具体的语法如下:
# 总路由
re_path(r"^app01/",include("app01.urls",namespace="app01")),
re_path(r"^app02/",include("app02.urls",namespace="app02"))
# 解析的时候
# app01
urlpatterns = [
url(r"^reg/",views.reg,name="reg")
]
# app02
urlpatterns = [
url(r"^reg/",views.reg,name="reg")
]
# 视图层:
reverse("app01:reg")
reverse("app02:reg")
# 模板层:
{% url "app01:reg" %}
{% url "app02:reg" %}
但其实,我们在起别名的时候只要保证别名不冲突,就没有必要使用名称空间。
一般情况下,有多个app的时候我们在起别名的时候会加上app的前缀,如name=‘app01_xxx’,这样就能解决了!
3.6路由层的转换器
path("page/<int:num>", views.test),
说明:1.path转换器:可以用来批量匹配一百个网页分别为page/1、page/2...等
2.语法为:<转换器类型:自定义名>
3.作用:若转换器类型匹配到对应类型的数据,则将数据按照关键字传参的方式传递给视图函数
4.转换器的类型:str:匹配除了"/"之外的非空字符串;int:匹配0或者任何正整数;# slug:匹配任意由ascll字母或数字以及连字符和下划线组成的短标签;path:匹配非空字段。