Django路由
路由就是根据用户请求的URL链接来判断对应的处理程序,并返回处理结果,也就是URL与Django的视图建立映射关系。
Django路由在urls.py配置,urls.py中的每一条配置对应相应的处理方法。
Django不同版本urls.py配置有点不一样
- Django1.1.x 版本
url()方法:普通路径和正则路径均可使用,需要自己手动添加正则首位限制符号。
from django.conf.urls import url # 用 url 需要引入
urlpatterns = [
url(r'^admin/$', admin.site.urls),
url(r'^index/$', views.index), # 普通路径
url(r'^articles/([0-9]{4})/$', views.articles), # 正则路径
]
-
Django 2.2.x之后的版本
-
path:用于普通路径,不需要自己手动添加正则首位限制符号,底层已经够添加。
-
re_path:用于正则路径,需要自己手动添加正则首位限制符号。
from django.urls import re_path # 用re_path 需要引入
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index), # 普通路径
re_path(r'^articles/([0-9]{4})/$', views.articles), # 正则路径
]
注:2.2.x版本也可以使用url()方法
正则路径中的分组
- 正则路径中的无名分组
无名分组按位置传参,一一对应。
views中除了request,其他形参的数量与urls中的分组数量一致。
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
re_path("^index/([0-9]{4})/$", views.index),
]
# views.py
from django.shortcuts import HttpResponse
def index(request,year):
print(year) # 一个形参代表路径中一个分组的内容,按顺序匹配
return HttpResponse('hello world')
- 正则路径中的有名分组
语法
(?P<组名>正则表达式)
有名分组按关键字传参,与位置顺序无关
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
re_path("^index/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.index),
]
# views.py
from django.shortcuts import HttpResponse
def index(request, year, month):
print(year, month) # 一个形参代表路径中一个分组的内容,按关键字对应匹配
return HttpResponse('hello world')
路由分发
使用路由分发(include),让每个app目录都单独拥有自己的urls。
步骤:
- 1、在每个app目录里都创建一个urls.py文件
- 2、在项目名称目录下的urls文件里,统一将路径分发给app目录
from django.contrib import admin
from django.urls import path,include # 从 django.urls 引入 include
urlpatterns = [
path('admin/', admin.site.urls),
path("app01/", include("app01.urls")),
path("app02/", include("app02.urls")),
]
在各自app目录下,写自己的urls.py文件,进行路径跳转。
# app01目录
from django.urls import path,re_path
from app01 import views # 从自己的 app 目录引入 views
urlpatterns = [
re_path(r'^login/(?P<m>[0-9]{2})/$', views.index, ),
]
反向解析
功能的增加,路由曾的url发生变化,就需要更改对应的视图层和模块层的url,非常麻烦,不便维护。
这个问题可以利用反向解析来解决,当路由层url发生改变,在视图层和模板层动态反向解析出更改后的url,免去修改的操作。
反向解析一般用在模板中的超链接及视图中的重定向。
- 普通路径
在urls.py中给路由起别名,name=‘路由别名’
path("login1/", views.login, name="login")
在views.py中,从django.urls中引入reverse,利用reverse(‘路由别名’)反向解析
return redirect(reverse("login"))
在模板templates中的HTML文件中,利用{% url “路由别名” %}反向解析。
<form action="{% url 'login' %}" method="post">
- 正则路径(无名分组)
在urls.py中给路由起别名,name="路由别名”
re_path(r"^login/([0-9]{2})/$", views.login, name="login")
在views.py中,利用reverse(‘路由别名’, args=(符合正则匹配的参数,))反向解析
return redirect(reverse("login",args=(10,)))
在模板templates中的HTML文件中利用{% url ‘路由别名’ 符合正则匹配的参数 %}反向解析
<form action="{% url 'login' 10 %}" method="post">
- 正则路径(有名分组)
在urls.py中给路由起别名,name=“路由别名”
re_path(r"^login/(?P<year>[0-9]{4})/$", views.login, name="login")
在views.py中,利用reverse(‘路由别名’, kwargs={‘分组名’: 符合正则匹配的参数})反向解析
return redirect(reverse("login", kwargs={"year":3333}))
在模板templates中的HTML文件中,利用{% url “路由别名” 分组名=符合正则匹配的参数 %}反向解析。
<form action="{% url 'login' year=3333 %}" method="post">
命名空间
命名空间(英语:Namespace)时表示标识符的可见范围。
使用命名空间可以解决,当在不同的app目录下的urls中定义相同的路由别名name时,可能会导致URL反向解析错误。
因为路由别名name没有作用域,Django在反向解析URL时,会在项目全局顺序搜索,当查找到第一个路由别名name指定URL时,立即返回。
格式
include(("app名称:urls","app名称"))
实例
path("app01/", include(("app01.urls","app01")))
path("app01/", include(("app02.urls","app02")))
在views.py中使用格式
reverse("app名称:路由别名")
实例
return redirect(reverse("app01:login")
在templates模板的HTML文件中使用格式
{% url "app名称:路由别名" %}
实例
<form action="{% url 'app01:login' %}" method="post">