Django的路由系统
一、URL配置
基本格式
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
参数说明:
1、正则表达式:一个正则表达式字符串
2、views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
3、参数:可选的要传递给视图函数的默认参数(字典形式)
4、别名:一个可选的name参数
插播:Django2.0版本和1.x版本的区别
Django2.0版本中的路由系统已经替换成下面的写法
官方文档
from django.urls import path
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),
]
Django2.0中的path
1、django2.0里面的path第一个参数不支持正则,你写什么就匹配,100%精准匹配
2、django2.0里面的re_path对应着django1.0里面的url
3、虽然django2.0里面的path不支持正则表达式,但是它提供五个默认的转换器
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
4、自定义转换器
1.正则表达式
2.类
3.注册
# 自定义转换器
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value # 占四位,不够用0填满,超了则就按超了的位数来!
register_converter(FourDigitYearConverter, 'yyyy')
PS:路由匹配到的数据默认都是字符串形式
路由工作过程:
注意:
1、第一个参数是正则表达式,匹配规则按照从上到下匹配,匹配到一个之后立即匹配,直接走后面的函数
2、网站首页路由
URL(r'^$', views.home)
3、网站报错页面路由
url(r", views.error)
二、正则表达式
2.1无名分组
无名分组(将加括号的正则表达式匹配到的内容当作位置参数自动传递给对应的视图函数)
url(r'^test/(\d+)/',views.test), # 匹配一个或多个数字
def test(request,xxx):
print(xxx)
return HttpResponse('test')
2.2有名分组
有名分组(将加括号的正则表达式匹配到的内容当作关键字参数自动传递给对应的视图函数)
url(r'^test/(?P<year>\d+)/',views.test), # 匹配一个或多个数字
def test(request,year):
print(year)
return HttpResponse('test')
注意:有名分组与无名分组不能结合使用
但是支持同一类型多个形式匹配
有名分组多个:
url(r'^test/(?P<year>\d+)/(?P<mouth>\d+)/', views.test),
无名分组多个:
url(r'^test/(\d+)/(\d+)/', views.test),
三、反向解析
定义:根据名字动态获取对应路径
from Django.shortcuts.import reverse
url(r'^index2333/$', views.index, name='index')
- 可以给每一个路由与视图函数对应关系起一个名字
- 这个名字能够唯一标识出对应的路径
- 注意这个名字不能重复是唯一的
前端使用:
{% url 'index' %}
{% url '给路由与视图函数对应关系起的一个名字' %}
后端使用:
reverse('index')
reverse('给路由与视图函数对应关系起的别名‘)
3.1 无名分组反向解析
url(r'^test/(\d+)/', views.test, name='checkout' )
后端使用
reverse(‘checkout’,args=(int,))
# 此处的int表示任意整数都可一,它匹配的是正则表达式中的(\d+)
前端使用
{% url ‘checkout’ int %}. #此处的int跟后端的含义一样
**示例:**
路由
url(r'^edit/(\d+)/',views.edit,name='edit')
视图函数:
from django.shortcuts import reverse
def edit(request, edit_id):
url = reverse('edit', args =(edit_id,))
前端模版语法
{% url 'edit' edit_id %}
a标签中的使用
{%for user_obj in user_list%}
<a href='edit/{{ user_obj.pk }}/'></a>
{% endfor %}
3.2有名分组反向解析
后端使用
#后端游名分组和无名分组都可以用这种形式
print( reverse ('checkout', args=(int,))) #参数以元祖形式
#独属有名分组的后端形式是
print( reverse ('checkout', kwargs={'yesr:10})). #参数以字典形式
前端使用
# 前端有名分组和无名分组都可以用这种形式
{% url 'checkout' int %}
#有名分组的专属形式是:
{% url 'checkout' year=int %}
总结:针对有名分组与无名分组的反向解析统一采用一种格式,后端(reverser(‘checkout’, args=(10,)),前端{% url ‘checkout’ 10 %}
反向解析的本质:目的是为了获取一个能够访问名字所对应的视图函数
四、路由分发
Django每一个app下面都可以有自己的urls.py路由层,temlates文件夹,static文件夹,
此时原来项目名下的urls.py(总路由)不再作路由与视图函数的匹配关系而是做路由的分发
步骤1在各个应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^index/',views.index)
]
步骤2.在总路由下用include做分发
from Django.conf.urls. import include
from app01 import urls as app01_urls # 其别名为了区分不同应用下的同名urls.py文件
from app02 import urls as app02_urls
# 路由分发 注意路由分发总路由千万不要$结尾
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))
五、名称空间(namespace)
目的:即使不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL
举个例子:
项目中的urls.py
from django.conf.urls import url, include
urlpatterns = [
url(r'^app01/', include('app01.urls', namespace='app01')),
url(r'^app02/', include('app02.urls', namespace='app02')),
]
app01中的urls.py
from django.conf.urls import url
from app01 import views
app_name = 'app01'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
app02中的urls.py
from django.conf.urls import url
from app02 import views
app_name = 'app02'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
现在,两个app中的url名称重复了,用reverse反转url的时候就可以通过名称空间的名称得到当前的url。
语法:
名称空间:url名称
模版中使用:
{% url 'app01:detail' pk=12 pp=99 %}
views中的函数使用
v = reverse('app01:detail', kwargs={'pk':11})
这样即使app中的url的命名相同,也可以反转得到正确的url了