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 模式,所有這些模式都以檢視為目標:homeaboutblog-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'),
]