Django 如何處理請求
Django 通過將傳入的 URL 路徑路由到檢視函式來處理請求。view 函式負責將響應返回給發出請求的客戶端。不同的 URL 通常由不同的檢視函式處理。要將請求路由到特定的檢視函式,Django 會檢視你的 URL 配置(或簡稱 URLconf)。預設專案模板定義 <myproject>/urls.py
中的 URLconf。
你的 URLconf 應該是一個 python 模組,它定義了一個名為 urlpatterns
的屬性,該屬性是 django.conf.urls.url()
例項的列表。每個 url()
例項必須至少定義一個正規表示式 (一個正規表示式)來匹配 URL,以及一個目標,它是一個檢視函式或一個不同的 URLconf。如果 URL 模式以檢視函式為目標,則最好為其命名,以便以後輕鬆引用該模式。
我們來看一個基本的例子:
# In <myproject>/urls.py
from django.conf.urls import url
from myapp.views import home, about, blog_detail
urlpatterns = [
url(r'^$', home, name='home'),
url(r'^about/$', about, name='about'),
url(r'^blog/(?P<id>\d+)/$', blog_detail, name='blog-detail'),
]
此 URLconf 定義了三種 URL 模式,所有這些模式都以檢視為目標:home
,about
和 blog-detail
。
url(r'^$', home, name='home'),
正規表示式包含一個起始錨點’^’,緊接著是一個結束錨’$’。此模式將匹配 URL 路徑為空字串的請求,並將它們路由到 myapp.views
中定義的 home
檢視。
url(r'^about/$', about, name='about'),
此正規表示式包含一個起始錨點,後跟文字字串 about/
和結束錨點。這將匹配 URL /about/
並將其路由到 about
檢視。由於每個非空 URL 都以/
開頭,因此 Django 可以方便地為你剪下第一個斜槓。
url(r'^blog/(?P<id>\d+)/$', blog_detail, name='blog-detail'),
這個正規表示式有點複雜。它定義了起始錨點和文字字串 blog/
,就像前面的模式一樣。下一部分 (?P<id>\d+)
被稱為捕獲組。捕獲組(如其名稱所示)捕獲字串的一部分,Django 將捕獲的字串作為引數傳遞給檢視函式。
捕獲組的語法是 (?P<name>pattern)
。name
定義組的名稱,這也是 Django 用於將引數傳遞給檢視的名稱。該模式定義了組匹配的字元。
在這種情況下,名稱為 id
,因此函式 blog_detail
必須接受名為 id
的引數。模式是\d+
。\d
表示該模式僅匹配數字字元。+
表示模式必須匹配一個或多個字元。
一些常見的模式:
blog-detail
模式中的捕獲組後面是文字/
和結束錨。
有效的網址包括:
/blog/1/ # passes id='1'
/blog/42/ # passes id='42'
例如,無效的網址是:
/blog/a/ # 'a' does not match '\d'
/blog// # no characters in the capturing group does not match '+'
Django 按照在 urlpatterns
中定義的相同順序處理每個 URL 模式。如果多個模式可以匹配相同的 URL,這一點很重要。例如:
urlpatterns = [
url(r'blog/(?P<slug>[\w-]+)/$', blog_detail, name='blog-detail'),
url(r'blog/overview/$', blog_overview, name='blog-overview'),
]
在上面的 URLconf 中,第二個模式是不可訪問的。該模式將匹配 URL /blog/overview/
,但不是呼叫 blog_overview
檢視,URL 將首先匹配 blog-detail
模式並使用引數 slug='overview'
呼叫 blog_detail
檢視。
為了確保 URL /blog/overview/
被路由到 blog_overview
檢視,模式應該放在 blog-detail
模式之上:
urlpatterns = [
url(r'blog/overview/$', blog_overview, name='blog-overview'),
url(r'blog/(?P<slug>[\w-]+)/$', blog_detail, name='blog-detail'),
]