{% raw %}
# URL調度器 #
簡潔、優雅的URL 模式在高質量的Web 應用中是一個非常重要的細節。Django 允許你任意設計你的URL,不受框架束縛。
不要求有`.php` 或`.cgi`,更不會要求類似`0,2097,1-1-1928,00` 這樣無意義的東西。
參見萬維網的發明者Berners-Lee 的[Cool URIs don’t change](http://www.w3.org/Provider/Style/URI),里面有關于為什么URL 應該保持整潔和有意義的卓越的論證。
## 概覽 ##
為了給一個應用設計URL,你需要創建一個Python 模塊,通常稱為URLconf(URL configuration)。這個模塊是純粹的Python 代碼,包含URL 模式(簡單的正則表達式)到Python 函數(你的視圖)的簡單映射。
映射可短可長,隨便你。它可以引用其它的映射。而且,因為它是純粹的Python 代碼,它可以動態構造。
Django 還提供根據當前語言翻譯URL 的一種方法。更多信息參見[國際化文檔](http://python.usyiyi.cn/django/topics/i18n/translation.html#url-internationalization)。
## Django 如何處理一個請求 ##
當一個用戶請求Django 站點的一個頁面,下面是Django 系統決定執行哪個Python 代碼使用的算法:
1. Django 決定要使用的根`URLconf` 模塊。通常,這個值就是`ROOT_URLCONF` 的設置,但是如果進來的`HttpRequest` 對象具有一個`urlconf` 屬性(通過中間件`request` `processing` 設置),則使用這個值來替換`ROOT_URLCONF` 設置。
2. Django 加載該Python 模塊并尋找可用的`urlpatterns`。它是`django.conf.urls.url()` 實例的一個Python 列表。
3. Django 依次匹配每個URL 模式,在與請求的URL 匹配的第一個模式停下來。
4. 一旦其中的一個正則表達式匹配上,Django 將導入并調用給出的視圖,它是一個簡單的Python 函數(或者一個基于類的視圖)。視圖將獲得如下參數:
+ 一個`HttpRequest` 實例。
+ 如果匹配的正則表達式沒有返回命名的組,那么正則表達式匹配的內容將作為位置參數提供給視圖。
+ 關鍵字參數由正則表達式匹配的命名組組成,但是可以被`django.conf.urls.url()`的可選參數`kwargs`覆蓋。
5. 如果沒有匹配到正則表達式,或者如果過程中拋出一個異常,Django 將調用一個適當的錯誤處理視圖。請參見下面的錯誤處理。
## 例子 ##
下面是一個簡單的 URLconf:
```
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
```
注:
+ 若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
+ 不需要添加一個前導的反斜杠,因為每個URL 都有。例如,應該是`^articles` 而不是 `^/articles`。
+ 每個正則表達式前面的'r' 是可選的但是建議加上。它告訴Python 這個字符串是“原始的” —— 字符串中任何字符都不應該轉義。參見Dive Into Python 中的解釋。
一些請求的例子:
+ `/articles/2005/03/` 請求將匹配列表中的第三個模式。Django 將調用函數`views.month_archive(request, '2005', '03')`。
+ `/articles/2005/3/` 不匹配任何URL 模式,因為列表中的第三個模式要求月份應該是兩個數字。
+ `/articles/2003/` 將匹配列表中的第一個模式不是第二個,因為模式按順序匹配,第一個會首先測試是否匹配。請像這樣自由插入一些特殊的情況來探測匹配的次序。
+ `/articles/2003` 不匹配任何一個模式,因為每個模式要求URL 以一個反斜線結尾。
+ `/articles/2003/03/03/` 將匹配最后一個模式。Django 將調用函數`views.article_detail(request, '2003', '03', '03')`。
## 命名組 ##
上面的示例使用簡單的、沒有命名的正則表達式組(通過圓括號)來捕獲URL 中的值并以位置 參數傳遞給視圖。在更高級的用法中,可以使用命名的正則表達式組來捕獲URL 中的值并以關鍵字 參數傳遞給視圖。
在Python 正則表達式中,命名正則表達式組的語法是`(?P<name>pattern)`,其中`name` 是組的名稱,`pattern` 是要匹配的模式。
下面是以上URLconf 使用命名組的重寫:
```
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
```
這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數。例如:
+ `/articles/2005/03/` 請求將調用`views.month_archive(request, year='2005', month='03')`函數,而不是`views.month_archive(request, '2005', '03')`。
+ `/articles/2003/03/03/` 請求將調用函數`views.article_detail(request, year='2003', month='03', day='03')`。
在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你可以在你的視圖函數定義中重新安排參數的順序。當然,這些好處是以簡潔為代價;有些開發人員認為命名組語法丑陋而繁瑣。
### 匹配/分組算法 ###
下面是URLconf 解析器使用的算法,針對正則表達式中的命名組和非命名組:
1. 如果有命名參數,則使用這些命名參數,忽略非命名參數。
2. 否則,它將以位置參數傳遞所有的非命名參數。
根據[傳遞額外的選項給視圖函數](http://python.usyiyi.cn/django/topics/http/urls.html#passing-extra-options-to-view-functions)(下文),這兩種情況下,多余的關鍵字參數也將傳遞給視圖。
## URLconf 在什么上查找 ##
URLconf 在請求的URL 上查找,將它當做一個普通的Python 字符串。不包括GET和POST參數以及域名。
例如,http://www.example.com/myapp/ 請求中,URLconf 將查找`myapp/`。
在 http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找`myapp/`。
URLconf 不檢查請求的方法。換句話講,所有的請求方法 —— 同一個URL的`POST`、`GET`、`HEAD`等等 —— 都將路由到相同的函數。
## 捕獲的參數永遠是字符串 ##
每個捕獲的參數都作為一個普通的Python 字符串傳遞給視圖,無論正則表達式使用的是什么匹配方式。例如,下面這行URLconf 中:
```
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
```
... `views.year_archive()` 的`year` 參數將是一個字符串,即使`[0-9]{4}` 值匹配整數字符串。
## 指定視圖參數的默認值 ##
有一個方便的小技巧是指定視圖參數的默認值。 下面是一個URLconf 和視圖的示例:
```
# URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
# View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
...
```
在上面的例子中,兩個URL模式指向同一個視圖`views.page` —— 但是第一個模式不會從URL 中捕獲任何值。如果第一個模式匹配,`page()` 函數將使用`num`參數的默認值"1"。如果第二個模式匹配,`page()` 將使用正則表達式捕獲的`num` 值。
## 性能 ##
`urlpatterns` 中的每個正則表達式在第一次訪問它們時被編譯。這使得系統相當快。
## urlpatterns 變量的語法 ##
`urlpatterns` 應該是`url()` 實例的一個Python 列表。
## 錯誤處理 ##
當Django 找不到一個匹配請求的URL 的正則表達式時,或者當拋出一個異常時,Django 將調用一個錯誤處理視圖。
這些情況發生時使用的視圖通過4個變量指定。它們的默認值應該滿足大部分項目,但是通過賦值給它們以進一步的自定義也是可以的。
完整的細節請參見[自定義錯誤視圖](http://python.usyiyi.cn/django/topics/http/views.html#customizing-error-views)。
這些值可以在你的根URLconf 中設置。在其它URLconf 中設置這些變量將不會生效果。
它們的值必須是可調用的或者是表示視圖的Python 完整導入路徑的字符串,可以方便地調用它們來處理錯誤情況。
這些值是:
+ `handler404` —— 參見`django.conf.urls.handler404`。
+ `handler500` —— 參見`django.conf.urls.handler500`。
+ `handler403` —— 參見`django.conf.urls.handler403`。
+ `handler400` —— 參見`django.conf.urls.handler400`。
## 包含其它的URLconfs ##
在任何時候,你的urlpatterns 都可以包含其它URLconf 模塊。這實際上將一部分URL 放置與其它URL 下面。
例如,下面是URLconf for the Django 網站自己的URLconf 中一個片段。它包含許多其它URLconf:
```
from django.conf.urls import include, url
urlpatterns = [
# ... snip ...
url(r'^community/', include('django_website.aggregator.urls')),
url(r'^contact/', include('django_website.contact.urls')),
# ... snip ...
]
```
注意,這個例子中的正則表達式沒有包含$(字符串結束匹配符),但是包含一個末尾的反斜杠。每當Django 遇到`include()`(`django.conf.urls.include()`)時,它會去掉URL 中匹配的部分并將剩下的字符串發送給包含的URLconf 做進一步處理。
另外一種包含其它URL 模式的方式是使用一個url() 實例的列表。例如,請看下面的URLconf:
```
from django.conf.urls import include, url
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
url(r'^charge/$', credit_views.charge),
]
urlpatterns = [
url(r'^$', main_views.homepage),
url(r'^help/', include('apps.help.urls')),
url(r'^credit/', include(extra_patterns)),
]
```
在這個例子中,`/credit/reports/` URL將被 `credit.views.report()` 這個Django 視圖處理。
這種方法可以用來去除URLconf 中的冗余,其中某個模式前綴被重復使用。例如,考慮這個URLconf:
```
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]
```
我們可以改進它,通過只聲明共同的路徑前綴一次并將后面的部分分組:
```
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
url(r'^permissions/$', views.permissions),
])),
]
```
### 捕獲的參數 ###
被包含的URLconf 會收到來之父URLconf 捕獲的任何參數,所以下面的例子是合法的:
```
# In settings/urls/main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
]
# In foo/urls/blog.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.blog.index),
url(r'^archive/$', views.blog.archive),
]
```
在上面的例子中,捕獲的"`username`"變量將被如期傳遞給包含的 URLconf。
## 嵌套的參數 ##
正則表達式允許嵌套的參數,Django 將解析它們并傳遞給視圖。當反查時,Django 將嘗試填滿所有外圍捕獲的參數,并忽略嵌套捕獲的參數。考慮下面的URL 模式,它帶有一個可選的`page` 參數:
```
from django.conf.urls import url
urlpatterns = [
url(r'blog/(page-(\d+)/)?$', blog_articles), # bad
url(r'comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]
```
兩個模式都使用嵌套的參數,其解析方式是:例如`blog/page-2/` 將匹配`blog_articles`并帶有兩個位置參數`page-2/` 和2。第二個`comments` 的模式將匹配`comments/page-2/` 并帶有一個值為2 的關鍵字參數`page_number`。這個例子中外圍參數是一個不捕獲的參數`(?:...)`。
`blog_articles` 視圖需要最外層捕獲的參數來反查,在這個例子中是`page-2/`或者沒有參數,而`comments`可以不帶參數或者用一個`page_number`值來反查。
嵌套捕獲的參數使得視圖參數和URL 之間存在強耦合,正如`blog_articles` 所示:視圖接收URL(`page-2/`)的一部分,而不只是視圖感興趣的值。這種耦合在反查時更加顯著,因為反查視圖時我們需要傳遞URL 的一個片段而不只是page 的值。
作為一個經驗的法則,當正則表達式需要一個參數但視圖忽略它的時候,只捕獲視圖需要的值并使用非捕獲參數。
## 傳遞額外的選項給視圖函數 ##
URLconfs 具有一個鉤子,讓你傳遞一個Python 字典作為額外的參數傳遞給視圖函數。
`django.conf.urls.url()` 函數可以接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。
例如:
```
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
```
在這個例子中,對于`/blog/2005/`請求,Django 將調用`views.year_archive(request, year='2005', foo='bar')`。
這個技術在[Syndication 框架](http://python.usyiyi.cn/django/ref/contrib/syndication.html) 中使用,來傳遞元數據和選項給視圖。
> 處理沖突
>
> URL 模式捕獲的命名關鍵字參數和在字典中傳遞的額外參數有可能具有相同的名稱。當這種情況發生時,將使用字典中的參數而不是URL 中捕獲的參數。
## 傳遞額外的選項給include() ##
類似地,你可以傳遞額外的選項給include()。當你傳遞額外的選項給include() 時,被包含的URLconf 的每一 行將被傳遞這些額外的選項。
例如,下面兩個URLconf 設置功能上完全相同:
設置一次:
```
# main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^blog/', include('inner'), {'blogid': 3}),
]
# inner.py
from django.conf.urls import url
from mysite import views
urlpatterns = [
url(r'^archive/$', views.archive),
url(r'^about/$', views.about),
]
```
設置兩次:
```
# main.py
from django.conf.urls import include, url
from mysite import views
urlpatterns = [
url(r'^blog/', include('inner')),
]
# inner.py
from django.conf.urls import url
urlpatterns = [
url(r'^archive/$', views.archive, {'blogid': 3}),
url(r'^about/$', views.about, {'blogid': 3}),
]
```
注意,額外的選項將永遠傳遞給被包含的URLconf 中的每一行,無論該行的視圖實際上是否認為這些選項是合法的。由于這個原因,該技術只有當你確定被包含的URLconf 中的每個視圖都接收你傳遞給它們的額外的選項。
## URL 的反向解析 ##
在使用Django 項目時,一個常見的需求是獲得URL 的最終形式,以用于嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用于處理服務器端的導航(重定向等)。
人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 毫不相關的專門的URL 生成機制,因為這樣容易導致一定程度上產生過期的URL。
換句話講,需要的是一個DRY 機制。除了其它有點,它還允許設計的URL 可以自動更新而不用遍歷項目的源代碼來搜索并替換過期的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計唯一的地方。你填充你的URLconf,然后可以雙向使用它:
+ 根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,并從URL 中提取它的參數需要的值。
+ 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。
第一種方式是我們在前面的章節中一直討論的用法。第二種方式叫做反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。
在需要URL 的地方,對于不同層級,Django 提供不同的工具用于URL 反查:
+ 在模板中:使用url 模板標簽。
+ 在Python 代碼中:使用`django.core.urlresolvers.reverse()` 函數。
+ 在更高層的與處理Django 模型實例相關的代碼中:使用`get_absolute_url()` 方法。
例子
考慮下面的URLconf:
```
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]
```
根據這里的設計,某一年nnnn對應的歸檔的URL是`/articles/nnnn/`。
你可以在模板的代碼中使用下面的方法獲得它們:
```
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
```
在Python 代碼中,這樣使用:
```
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
```
如果出于某種原因決定按年歸檔文章發布的URL應該調整一下,那么你將只需要修改URLconf 中的內容。
在某些場景中,一個視圖是通用的,所以在URL 和視圖之間存在多對一的關系。對于這些情況,當反查URL 時,只有視圖的名字還不夠。請閱讀下一節來了解Django 為這個問題提供的解決辦法。
## 命名URL 模式 ##
為了完成上面例子中的URL 反查,你將需要使用命名的URL 模式。URL 的名稱使用的字符串可以包含任何你喜歡的字符。不只限制在合法的Python 名稱。
當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱沖突。如果你的URL 模式叫做`comment`,而另外一個應用中也有一個同樣的名稱,當你在模板中使用這個名稱的時候不能保證將插入哪個URL。
在URL 名稱中加上一個前綴,比如應用的名稱,將減少沖突的可能。我們建議使用`myapp-comment` 而不是`comment`。
## URL 命名空間 ##
### 簡介 ###
URL 命名空間允許你反查到唯一的[命名URL 模式](http://python.usyiyi.cn/django/topics/http/urls.html#naming-url-patterns),即使不同的應用使用相同的URL 名稱。第三方應用始終使用帶命名空間的URL 是一個很好的實踐(我們在教程中也是這么做的)。類似地,它還允許你在一個應用有多個實例部署的情況下反查URL。換句話講,因為一個應用的多個實例共享相同的命名URL,命名空間將提供一種區分這些命名URL 的方法。
在一個站點上,正確使用URL 命名空間的Django 應用可以部署多次。例如,`django.contrib.admin` 具有一個`AdminSite` 類,它允許你很容易地[部署多個管理站點的實例](http://python.usyiyi.cn/django/ref/contrib/admin/index.html#multiple-admin-sites)。在下面的例子中,我們將討論在兩個不同的地方部署教程中的polls 應用,這樣我們可以為兩種不同的用戶(作者和發布者)提供相同的功能。
一個URL 命名空間有兩個部分,它們都是字符串:
**應用命名空間**
它表示正在部署的應用的名稱。一個應用的每個實例具有相同的應用命名空間。例如,可以預見Django 的管理站點的應用命名空間是'`admin`'。
**實例命名空間**
它表示應用的一個特定的實例。實例的命名空間在你的全部項目中應該是唯一的。但是,一個實例的命名空間可以和應用的命名空間相同。它用于表示一個應用的默認實例。例如,Django 管理站點實例具有一個默認的實例命名空間'admin'。
URL 的命名空間使用':' 操作符指定。例如,管理站點應用的主頁使用'`admin:index`'。它表示'`admin`' 的一個命名空間和'`index`' 的一個命名URL。
命名空間也可以嵌套。命名URL'`sports:polls:index`' 將在命名空間'`polls`'中查找'`index`',而`poll` 定義在頂層的命名空間'`sports`' 中。
### 反查帶命名空間的URL ###
當解析一個帶命名空間的URL(例如'`polls:index`')時,Django 將切分名稱為多個部分,然后按下面的步驟查找:
1. 首先,Django 查找匹配的應用的命名空間(在這個例子中為'`polls`')。這將得到該應用實例的一個列表。
2. 如果有定義當前 應用,Django 將查找并返回那個實例的URL 解析器。當前 應用可以通過請求上的一個屬性指定。希望可以多次部署的應用應該設置正在處理的`request`上的`current_app` 屬性。
```
Changed in Django 1.8:
在以前版本的Django 中,你必須在用于渲染模板的每個`Context` 或 `RequestContext`上設置`current_app` 屬性。
```
當前應用還可以通過`reverse()` 函數的一個參數手工設定。
3. 如果沒有當前應用。Django 將查找一個默認的應用實例。默認的應用實例是[實例命名空間](http://python.usyiyi.cn/django/topics/http/urls.html#term-instance-namespace) 與[應用命名空間](http://python.usyiyi.cn/django/topics/http/urls.html#term-application-namespace) 一致的那個實例(在這個例子中,`polls` 的一個叫做'`polls`' 的實例)。
4. 如果沒有默認的應用實例,Django 將該應用挑選最后部署的實例,不管實例的名稱是什么。
5. 如果提供的命名空間與第1步中的[應用命名空間](http://python.usyiyi.cn/django/topics/http/urls.html#term-application-namespace) 不匹配,Django 將嘗試直接將此命名空間作為一個[實例命名空間](http://python.usyiyi.cn/django/topics/http/urls.html#term-instance-namespace)查找。
如果有嵌套的命名空間,將為命名空間的每個部分重復調用這些步驟直至剩下視圖的名稱還未解析。然后該視圖的名稱將被解析到找到的這個命名空間中的一個URL。
### 例子 ###
為了演示解析的策略,考慮教程中polls 應用的兩個實例:'`author-polls`' 和'`publisher-polls`'。假設我們已經增強了該應用,在創建和顯示投票時考慮了實例命名空間。
```
#urls.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')),
]
```
```
#polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
...
]
```
根據以上設置,可以使用下面的查詢:
+ 如果其中一個實例是當前實例 —— 如果我們正在渲染'`author-polls`' 實例的`detail` 頁面 —— '`polls:index`' 將解析成'`author-polls`' 實例的主頁面;例如下面兩個都將解析成"`/author-polls/`"。
在基于類的視圖的方法中:
```
reverse('polls:index', current_app=self.request.resolver_match.namespace)
```
和在模板中:
```
{% url 'polls:index' %}
```
注意,在模板中的反查需要添加`request` 的`current_app` 屬性,像這樣:
```
def render_to_response(self, context, **response_kwargs):
self.request.current_app = self.request.resolver_match.namespace
return super(DetailView, self).render_to_response(context, **response_kwargs)
```
+ 如果沒有當前實例 —— 如果我們在站點的其它地方渲染一個頁面 —— '`polls:index`' 將解析到最后注冊的`polls`的一個實例。因為沒有默認的實例(命名空間為'polls'的實例),將使用注冊的`polls` 的最后一個實例。它將是'`publisher-polls`',因為它是在`urlpatterns`中最后一個聲明的。
+ '`author-polls:index`' 將永遠解析到 '`author-polls`' 實例的主頁('`publisher-polls`' 類似)。
如果還有一個默認的實例 —— 例如,一個名為'`polls`' 的實例 —— 上面例子中唯一的變化是當沒有當前實例的情況(上述第二種情況)。在這種情況下 '`polls:index`' 將解析到默認實例而不是`urlpatterns` 中最后聲明的實例的主頁。
### URL 命名空間和被包含的URLconf ###
被包含的URLconf 的命名空間可以通過兩種方式指定。
首先,在你構造你的URL 模式時,你可以提供 應用 和 實例的命名空間給`include()` 作為參數。例如:
```
url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
```
這將包含`polls.urls` 中定義的URL 到應用命名空間 '`polls`'中,其實例命名空間為'`author-polls`'。
其次,你可以include 一個包含嵌套命名空間數據的對象。如果你`include()` 一個`url()` 實例的列表,那么該對象中包含的URL 將添加到全局命名空間。然而,你還可以`include()` 一個3個元素的元組:
```
(<list of url() instances>, <application namespace>, <instance namespace>)
```
例如:
```
from django.conf.urls import include, url
from . import views
polls_patterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
]
url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),
```
這將include 命名的URL 模式到給定的應用和實例命名空間中。
例如,Django 的管理站點部署的實例叫`AdminSite`。`AdminSite` 對象具有一個`urls` 屬性:一個3元組,包含管理站點中的所有URL 模式和應用的命名空間'`admin`'以及管理站點實例的名稱。你`include()`到你項目的`urlpattern`s 中的是這個`urls` 屬性。
請確保傳遞一個元組給`include()`。如果你只是傳遞3個參數:`include(polls_patterns, 'polls', 'author-polls')`,Django 不會拋出一個錯誤,但是根據`include()` 的功能,'`polls`' 將是實例的命名空間而'`author-polls`' 將是應用的命名空間,而不是反過來的。
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[URLconfs](https://docs.djangoproject.com/en/1.8/topics/http/urls/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
{% endraw %}
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架