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-路由重定向

   关闭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="{% url 'test'%}">前端反向解析</a>

url(r'^test/',views.login,name="test"),

def test(request):
	,,,

   无名分组前端反向解析:

<a href="{% url 'test' 111 222 333 %}">前端反向解析(无名分组)</a>  # 参数必须一一对应

url(r'^test/-(\d+)-(\d+)-(\d+)',views.login,name="test"),

def test(request,v1,v2,v3):  # 参数必须一一对应
	...

   有名分组前端反向解析:

<a href="{% 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的代码冗余度,此外还可以进行非常给力的分组开发。

   image-20200909221712367

基本使用

   首先我们要在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
]
posted @ 2020-09-10 10:42  云崖先生  阅读(317)  评论(0编辑  收藏  举报