Django 路由层

微信扫一扫,分享到朋友圈

Django 路由层

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/', admin.site.urls),
url(r'^f', views.f1),
url(r'^f', views.f2),
url(r'^f', views.f3),
]
# 无论输入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,v2,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+)/$', views.date),

视图层中的处理函数

def date(request,year,month,day):  # 必须与分组名相同
return HttpResponse("{0}-{1}-{2}".format(year,month,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+)/$', views.date),
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="https://www.tuicool.com/articles/AnMfEnz/{% url 'test'%}">前端反向解析</a>
url(r'^test/',views.login,name="test"),
def test(request):
,,,

无名分组前端反向解析:

<a href="https://www.tuicool.com/articles/AnMfEnz/{% url 'test' 111 222 333 %}">前端反向解析(无名分组)</a>  # 参数必须一一对应
url(r'^test/-(\d+)-(\d+)-(\d+)',views.login,name="test"),
def test(request,v1,v2,v3):  # 参数必须一一对应
...

有名分组前端反向解析:

<a href="https://www.tuicool.com/articles/AnMfEnz/{% test 'login' 111 222 333 %}">前端反向解析(有名分组)</a> # 参数必须一一对应
url(r'^test/-(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)',views.login,name="test"),
def test(request,year,month,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+)',views.index,name="index"), # 匹配规则,跳转到index
def index(request,v1,v2,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+)',views.index,name="index"), # 匹配规则,跳转到index
def index(request, year, month, day):
...

路由分发

Django 允许在每个 APP 下拥有 templates 文件夹, static 文件夹,当然也可以拥有 urls.py 文件夹。

路由分发的作用在于缓解项目全局文件夹下 urls.py 的代码冗余度,此外还可以进行非常给力的分组开发。

基本使用

首先我们要在 app01app02 下创建两个 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/',views.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')),
url(r'app02/', 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/', include('app01.urls')),
url(r'app02/', include('app02.urls')),  # 注意,app02在下面
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',views.f1,name="f1") # app01里的f1
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',views.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/',views.f1,name="f1") # app01里的f1
]
# ======================================
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'f1/',views.f1,name="f2") # app02里的f1
]

微信扫一扫,分享到朋友圈

Django 路由层

2020年飓风季的热带风暴名称用完后 科学家将启用希腊字母来命名

上一篇

世界首台便携式核磁共振成像仪在测试中取得可喜结果

下一篇

你也可能喜欢

Django 路由层

长按储存图像,分享给朋友