08 url之路由控制
简单路由配置
urls.py 配置路由
正则路由匹配:
类似re正则,无需像path那样路径必须一样。匹配从上至下,能匹配到即刻返回,不会再朝下匹配
from django.urls import path,re_path
- ^以什么开头
- $以什么结尾
from django.urls import re_path from app01 import views urlpatterns = [ re_path(r'^special_case_2003/$',views.special_case_2003) ]
- ([0-9]){4},只要在url匹配中进行分组后,会自动将分组内容传递给位置参数,所以处理函数必须有相应位置参数
re_path(r'^special_case/([0-9]{4})/$',views.special_case_2003) #可匹配special_case/2001/,special_case/2002/,special_case/2003/,special_case/2004/等类似url
def year_archive(request,year): return HttpResponse("year:%s" % year)
- 在正则中有多个分组,则需多个位置参数
re_path(r'^archive/([0-9]{4})/([0-9]{2})$',views.math_archive),
def math_archive(request,year,math): return HttpResponse("year:%s年%s月" % (year,math))
注意:
- 若要从url中捕获一个值,只需要在周围放置一对圆括号
- 不需要添加一个前置反斜杠,因为每个url都有
- 每个正则前面的'r'可选,但建议放置,告诉python为原始字符,任何字符都无需转义
HttpResponse
自己构造响应体
from django.shortcuts import render,HttpResponse
def special_case_2003(request): #直接给浏览器返回一个h1标签 return HttpResponse("<h1>special_case_2003</h1>")
有名分组
即对url正则中捕获的参数进行命名,避免顺序混乱。即通过关键字参数进行传参。
?P<m>
re_path(r'^archive/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})$',views.math_archive),
在视图函数中接收参数时,位置颠倒无所谓
def math_archive(request,m,y): return HttpResponse("year:%s年%s月" % (y,m))
路由分发
将各个app的路由分开定义,,通过include方法进行指定,由全局路由进行分发,分发到应用上
在应用下面新建一个urls.py文件
在本urls文件中,单独定义路由
from django.urls import re_path,path from app01 import views urlpatterns = [ path('timer/', views.timer), re_path(r'^special_case_2003/$',views.special_case_2003), re_path(r'^archive/([0-9]{4})/$',views.year_archive), re_path(r'^archive/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})$',views.math_archive), ]
在全局urls文件中,通过include方法对其接入
from django.urls import path,re_path,include urlpatterns = [ #分发路由 re_path(r"app01/",include("app01.urls")) ]
浏览器中访问新的路径
路由反向解析
- request.GET获取所有get方法的数据
- request.POST获取所有post方法的数据
在urls中定义path的时候给取别名
path('logins/', views.login,name="login")
在html模板中通过固定方式获取动态的url地址,别名相同即可
<form action="{% url 'login' %}" method="post"> <input type="text" name="name" placeholder="用户名"> <input type="password" name="pwd" placeholder="密码"> <input type="submit" value="登录"> </form>
render的时候会自动查找同名的url,避免path中路径修改后需要到html中同步修改
视图函数中使用反向解析
路由中添加名称空间后,在url中使用反向解析一定要加上名称空间前缀,冒号分割
与访问的路由无关系
首先导入反向解析模块
from django.urls import reverse
给urlpath起别名
re_path(r'^special_case_2003/$',views.special_case_2003,name="s_c_2003")
在视图函数中即可使用
def special_case_2003(request): url=reverse("s_c_2003") print(url)
反向解析带组的域名,需要添加相应参数
url中添加了分组
re_path(r'^archive/([0-9]{4})/$',views.year_archive,name="y")
视图函数中访问会出现报错
def special_case_2003(request): url2=reverse("y") print(url2)
此时需要给符合正则的参数
def special_case_2003(request): url1=reverse("s_c_2003") print(url1) url2=reverse("y",args=(2008,)) print(url2) return HttpResponse("<h1>special_case_2003</h1>")
路由之名称空间
路由中添加名称空间后,在url中使用反向解析一定要加上名称空间前缀,冒号分割
不同的app中可能存在同名的路径别名,这样就会出现冲突
如,在app01中定义一个name='index'的别名
re_path("index/",views.index,name="index")
如,在app02中同样定义一个name='index'的别名
re_path("index/",views.index,name="index")
此时,在视图函数中反向解析则会出问题,在不同的应用中反向解析出来的域名是一样的
我们在全局include应用urls时,添加名称空间,元祖的方式传入
re_path(r"^app01/",include(("app01.urls",'app01'))), re_path(r"^app02/",include(("app02.urls",'app02')))
在视图函数中反向解析的时候,添加名称空间和别名即可解决
app01中
def index(request): url=reverse('app01:index') print(url) return HttpResponse("app01 index")
app02中
def index(request): url = reverse('app02:index') print(url) return HttpResponse("<h2>app02 index</h2>")
在不同的应用中反向解析同名路径别名
路由控制path方法
在url中匹配成功的值都是字符串,容易导致数据类型错误
def math_archive(request,m,y): print(type(y),type(m))
相同的规则可能在不同的url中出现,修改起来比较麻烦
Django2.0中出现path函数,可解决上面问题
- 使用尖括号从url中捕获值
- 捕获值中可以包含一个类型转换器
- 无需添加前置反斜杠
支持的转换器
- str:匹配除了路径分隔符(/)以外的所有非空字符,默认形式
- int:匹配整型
- slug:匹配字面,数字,下划线组成的字符串
- uuid:匹配格式化的uuid如ddddd-33333-fffffff
- path:匹配非空字符串,包含路径分隔符
path("index2/<int:year>"),
在视图函数中查看year参数类型
def index(request,year): print(type(year)) return HttpResponse("app01 index")
int类型
自定义转换器
class MonConvert: regex="[0-9]{2}" def to_python(self,value): return int(value) def to_rul(self,value): return '%04d' % value
在urls中注册自定义转换器
from django.urls import register_converter register_converter(MonConvert,'mm')
在视图函数中打印类型
def path_month(request,month): print(type(month)) return HttpResponse("app01.path_month")