Django路由层
Django 路由层的功能就是匹配用户的资源请求,通过资源匹配路径来运行相应的视图层功能。
路径匹配
匹配顺序
Django 中的资源请求路径匹配是按照从上至下的顺序进行。
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/',admin.site.urls),# ↓
url(r'^f1/',views.f1),# ↓
url(r'^f2/',views.f2),# ↓
url(r'^f3/',views.f3),# ↓
]
正则匹配
匹配方式为正则匹配,因此要注意使用^ 与$ 的使用。
由于匹配行为是从上至下,所以在定义时一定要注意顺序。
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/',url(r'^f',]
# 无论输入f几,都是进入的f1的处理函数。
介绍两个关于主页和尾页的匹配规则
主页:'^$' 此时直接访问地址即可访问成功
尾页:'' 注意放在最后,这代表没匹配成功时将会弹出的信息,可以定义一个404 的页面进行返回。
重新匹配
如果第一次匹配没匹配上,那么在第二次匹配时Django 会要求浏览器对路径进行加/ 的处理重新再匹配一次,所以你将看到以下现象。
有两次请求:

关闭Django 要求浏览器加/ 的重新匹配行为,可在设置文件中加上如下代码:
APPEND_SLASH = False # 默认为True
匹配分组
匹配分组常用于提取出请求资源地址上一些能够被利用的信息,如id ,日期等。
分组中的数据将以参数形式传递给视图函数。
无名分组
单纯的分组,不取名字即为无名分组。
注意:无名分组匹配到的组内容会当作位置参数传递给后面的视图函数。
视图层匹配规则
url(r'^date/(d+)-(d+)-(d+)/$',views.date),
视图层中的处理函数
def date(request,v1,v2,v3): # 位置与分组一一对应即可
return HttpResponse("{0}-{1}-{2}".format(v1,v3))
请求的URL
http://127.0.0.1:8000/date/2020-01-28/
最终结果
2020-01-28
有名分组
有名分组即为分组取一个名字。
注意:有名分组匹配到的组内容会当作关键字参数传递给后面的视图函数,这代表视图函数中的参数与分组名字必须一致。
视图层匹配规则
url(r'^date/(?P<year>d+)-(?P<month>d+)-(?P<day>d+)/$',year,month,day): # 必须与分组名相同
return HttpResponse("{0}-{1}-{2}".format(year,day))
请求的URL
http://127.0.0.1:8000/date/2020-01-28/
最终结果
2020-01-28
混合使用
需要注意的是Django 中不支持无名与有名分组的混合使用。
如果混合使用,无名分组将拿不到数据。
http://127.0.0.1:8000/date/2020-01-28/
url(r'^date/(d+)-(?P<month>d+)-(?P<day>d+)/$',def date(request,*args,**kwargs):
return HttpResponse("{0}-{1}".format(args,kwargs))
# ()-{'month': '01','day': '28'}
反向解析
为URL 匹配规则起一个别名,通过该别名可以转换为请求资源路径。
匹配别名
可以为匹配规则取一个别名,但是一定要注意!别名不能出现冲突。
url(r'^login/',views.login,name="login"),
前端解析
如果前端中都写固定的请求资源路径,那么该路径的匹配规则一改就都匹配不到了。
所以更推荐取别名来使用反向解析来进行操作。即点击<a> 标签跳转到test 视图函数处理中。
无参数前端反向解析:
<a href="{% url 'test'%}">前端反向解析</a>
url(r'^test/',name="test"),def test(request):,
无名分组前端反向解析:
<a href="{% url 'test' 111 222 333 %}">前端反向解析(无名分组)</a> # 参数必须一一对应
url(r'^test/-(d+)-(d+)-(d+)',def test(request,v3): # 参数必须一一对应
...
有名分组前端反向解析:
<a href="{% test 'login' 111 222 333 %}">前端反向解析(有名分组)</a> # 参数必须一一对应
url(r'^test/-(?P<year>d+)-(?P<month>d+)-(?P<day>d+)',day): # 参数必须一一对应
...
后端解析
后端的反向解析常用在跳转中,如登陆完成后跳转到首页就可以使用后端反向解析。
后端使用反向解析,要先进行模块功能的导入。
这是最常用的,后端无参反向解析。
from django.shortcuts import reverse
def login(request):
return redirect(reverse('index')) # 登录完成后跳转到index页面
url(r'^index/',views.index,name="index"),# 匹配规则,跳转到index
def index(request):
...
如果后端反向解析的匹配规则中带有无名分组,则需要使用args 关键字参数将参数带上。
from django.shortcuts import reverse
def login(request):
return redirect(reverse('index',args=(111,222,333)))
url(r'^index/-(d+)-(d+)-(d+)',# 匹配规则,跳转到index
def index(request,v3):
...
如果后端反向解析的匹配规则中带有有名分组,则需要使用kwargs 关键字参数将参数带上。
def login(request):
return redirect(reverse('index',kwargs={"year": 2020,"month": 12,"day": 28}))
url(r'^index/--(?P<year>d+)-(?P<month>d+)-(?P<day>d+)',day):
...
路由分发
Django 允许在每个APP 下拥有templates 文件夹,static 文件夹,当然也可以拥有urls.py 文件夹。
路由分发的作用在于缓解项目全局文件夹下urls.py 的代码冗余度,此外还可以进行非常给力的分组开发。

基本使用
首先我们要在app01 与app02 下创建两个urls.py 。
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'f1/',views.f1,name="app01_f1")
]
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',name="app02_f1")
]
然后要在项目全局文件夹下的urls.py 中导入路由分发模块,然后导入app01 以及app02 下的urls.py 。
from django.conf.urls import url
from django.conf.urls import include # 导入路由分发模块
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'app01/',include(app01_urls)),url(r'app02/',include(app02_urls)),]
这样在url 中输入不同的前缀就能访问不同的APP 下对应的视图功能。
http://127.0.0.1:8000/app01/f1/ # app01的urls处理该请求
http://127.0.0.1:8000/app02/f1/ # app02的urls处理该请求
快捷使用
基本的路由分发使用还需要在项目全局文件夹下的urls.py 中导入不同APP 中的urls.py ,这样有点繁琐。
其实可以直接如下代码这样做更加简便,都不用导入不同APP 下的urls.py 了。
from django.conf.urls import url
from django.conf.urls import include # 导入路由分发模块
urlpatterns = [
url(r'app01/',include('app01.urls')),include('app02.urls')),]
命名空间
如果不同的APP 中,匹配别名相同则会造成命名空间冲突的问题。
此时我们需要在项目总文件夹的urls.py 中对路由分发的路径使用命名空间,然后才可以使用反向解析。
reverse("f1") # 命名空间冲突,始终解析的是app02下的f1
{% url 'f1' %}
# ======================================
from django.conf.urls import url
from django.conf.urls import include # 导入路由分发模块
urlpatterns = [
url(r'app01/',# 注意,app02在下面
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',name="f1") # app01里的f1
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',name="f2") # app02里的f1
]
reverse("app01:f1") # 反向解析时使用先拿到命名空间,再那里面的路径别名
{% url 'app01:f1' %}
# ======================================
from django.conf.urls import url
from django.conf.urls import include # 导入路由分发模块
urlpatterns = [
url(r'app01/',include('app01.urls',namespace="app01")),# 命名空间 app01
url(r'app02/',include('app02.urls',namespace="app02")),# 命名空间 app02
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',name="f2") # app02里的f1
]
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|