1. 程式人生 > 其它 >django請求生命週期流程與路由層相關知識

django請求生命週期流程與路由層相關知識

目錄

請求生命週期流程圖

django請求生命週期流程圖

路由層之路由匹配

我們都知道,路由層是匹配對應關係用的,那麼它是怎麼匹配上的呢?

urlpatterns = [
    url(r'^index/', views.index),
]

url方法的第一個引數其實是一個正則表示式,只要使用者輸入的地址字尾與內容匹配上,就會執行對應的檢視函式。

並且django有一個二次追加斜槓機制,如果你在輸入地址字尾時末尾沒有加斜槓,django會先匹配一次,如果匹配不上,那麼django還會讓瀏覽器預設加斜槓再次傳送請求,比如:

# 第一次匹配
http://127.0.0.1:8000/index

# 匹配不上加斜槓再次傳送請求
http://127.0.0.1:8000/index/

如果想要取消這個斜槓機制,那麼可以在settings.py加上:

APPEND_SLASH = False

因為是正則表示式,所以比如像上述程式碼中的例子,我在位址列輸入:

http://127.0.0.1:8000/index/abcde/66

或者:

http://127.0.0.1:8000/index/

都是可以匹配到正則:^index/ 的

拓展

讓使用者不需要輸入地址字尾就可以訪問到指定頁面:

urlpatterns = [
    url(r'^$', views.index),
]

也可以定義一個尾頁, 使用者輸入一個沒有對應關係的直接返回:

urlpatterns = [
    url(r'.*',views.error),
]

無名有名分組

無名分組

我們都知道,路由匹配成功之後就會呼叫檢視函式,並且預設情況下會自動給檢視函式傳遞一個request位置引數。

但是如果正則表示式中加了括號,那麼就不止傳遞一個request位置引數了,還會傳遞括號內正則表示式匹配到的內容。

urlpatterns = [
    url(r'^index/(.*)', views.index),
]

如果正則加了一個括號,那麼檢視函式就需要多寫一個形參用於接收匹配到的內容,不然會報錯。

def index(request, aa):
    return HttpResponse(aa)

這個就是無名分組。

有名分組

python中的正則表示式加括號是可以給括號內的內容進行命名的,這裡的正則表示式自然也可以。

給括號內的內容命名為address:

urlpatterns = [
    url(r'^index/(?P<address>.*)', views.index),
]

給括號內命名後,檢視函式就需要一個名字相同的形參接收:

def index(request, address):
    return HttpResponse(address)

這個就是有名分組。

補充說明

1.無名分組需要一個形參接收括號內的內容,名字隨意。

2.有名分組也需要一個形參接收括號內的內容,名字要與正則表示式裡的名字相同。

3.無名分組是位置傳參,有名分組是關鍵字傳參。

4.無名分組與有名分組不能混合使用,單個可以重複使用。

反向解析

前言:html中a標籤的href可以寫網址的全稱,也可以寫字尾,寫字尾會自動補全當前ip和port。

<a href='index'>點我跳轉index</a>  
<!--href='127.0.0.1:8000/index' -->

如上述標籤可以跳轉到127.0.0.1:8000/index,但是如果我路由匹配表示式出現了變化,那麼這個地址就無法跳轉到我想要的頁面了,比如:

# 原本
url(r'^index/', views.index)
# 修改後
url(r'^index123/', views.index)

這個時候a標籤就失效了,這該如何解決呢?反向解析就可以解決這個問題。

反向解析

通過反向解析可以獲取到一個結果,該結果可以訪問到一個路由。這麼說可能有點模糊,我們來看實戰:

第一步:給對應關係起別名

url(r'^index/', views.index, name='index_view')

第二步:使用模板語法修改a標籤

<a href="{% url 'index_view' %}">點我跳轉index</a>  

這個時候隨意修改路由的匹配表示式都會不出現a標籤無法跳轉。

後端也可以檢視‘index_view’對應的路由:

from django.shortcuts import reverse
reverse('index_view')  # 對應路由

根據這個路由,我們也可以進行重定向:

from django.shortcuts import reverse
def index(request):
	return redirect(reverse('index_view'))

無名有名分組反向解析

無名分組反向解析

如果你在設定路由時使用了無名分組,那麼你括號內的正則表示式的內容,需要人為指定。比如如下路由:

url(r'^index/(.*)', views.index, name='index_view')

這時候你的a標籤需要指定內容,因為對於表示式 '^index/(.*)' 有多種方式匹配到,a標籤不知道該使用哪個,所以需要人為指定。

比如我指定括號內的內容為:123

<a href="{% url 'index_view' 123 %}">點我跳轉index</a>  

後端也需要指定:

from django.shortcuts import reverse
reverse('index_view', args=(123,))  # /index/123

有名分組反向解析

如果你在設定路由時使用了有名分組,那麼同理,需要人為指定內容。

路由:命名為address

url(r'^index/(?P<address>.*)', views.index, name='index_view')

a標籤:設定address為123,兩種方式都可

<a href="{% url 'index_view' 123 %}">點我跳轉index</a>
<a href="{% url 'index_view' address=123 %}">點我跳轉index</a>  

後端:兩種方式都可

from django.shortcuts import reverse
reverse('index_view', args=(123,))  # /index/123
reverse('index_view', kwargs=('address':123))  # /index/123

路由分發

如果一個django專案特別龐大,裡面有很多應用,每個應用下有很多對應關係,這種情況如果把路由對應關係都寫在專案同名資料夾下的urls.py檔案下是明顯不合理的,所以我們要把路由對應關係拆分開。

django支援每個應用都可以有自己獨立的路由層、模板層、靜態檔案、檢視層(預設)、模型層(預設)。

每個應用編寫好自己的功能後,最後只需要整合一下就可以了。並且防止出現不同應用中出現相同路由,可以通過應用字首區分,並且用到一個include方法:

總路由:整個應用app01與app02

from django.conf.urls import url, 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)),
]

簡寫:

from django.conf.urls import url, include

urlpatterns = [
    url(r'^app01/', include('app01.urls')),
    url(r'^app02/', include('app02.urls')),
]

此時,訪問應用app01下的index就需要這麼輸入:

http://127.0.0.1:8000/app01/index/

名稱空間

不同的應用,設定路由時可能會使用相同的別名,比如:

應用app01路由:

urlpatterns = [
    url(r'^index/', views.index, name='index_view'),
]

應用app02路由:

urlpatterns = [
    url(r'^index/', views.index, name='index_view'),
]

a標籤:

<a href="{% url 'index_view' %}">點我跳轉index</a>
<a href="{% url 'index_view' %}">點我跳轉index</a>

此時我就無法讓我的a標籤都可以跳到應用app01下index或者應用app02下index,它只能跳轉到其中一個。

解決方法

方法一:總路由新增名稱空間

urlpatterns = [
    url(r'^app01/', include('app01.urls', namespace='app01')),
    url(r'^app02/', include('app02.urls', namespace='app02')),
]

a標籤:

<a href="{% url 'app01:index_view' %}">點我跳轉index</a>
<a href="{% url 'app02:index_view' %}">點我跳轉index</a>

方式二:應用路由起別名加上應用字首,如

urlpatterns = [
    url(r'^index/', views.index, name='app01_index_view'),
]

從根本解決問題。