在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ URL調(diào)度器
編寫自定義存儲系統(tǒng)
高級
編寫你的第一個Django應(yīng)用,第5部分
視圖層
Django管理文檔生成器
編寫你的第一個 Django 程序 第3部分
編寫你的第一個Django應(yīng)用,第6部分
模型層
中間件
測試
數(shù)據(jù)庫訪問優(yōu)化
文件上傳
中間件
驗(yàn)證器
基于類的內(nèi)建通用視圖
部署靜態(tài)文件
使用Django認(rèn)證系統(tǒng)
高級教程:如何編寫可重用的應(yīng)用
Model 類參考
Django 初探
使用Django輸出PDF
模型的實(shí)例
模型
文件上傳
進(jìn)行原始的sql查詢
面向程序員
中間件
編寫數(shù)據(jù)庫遷移
TemplateResponse 和 SimpleTemplateResponse
異常
Django中的測試
基礎(chǔ)
管理器
File對象
URL調(diào)度器
加密簽名
國際化和本地化
日志
查詢集
django-admin 和 manage.py
使用基于類的視圖處理表單
聚合
內(nèi)建基于類的視圖的API
如何使用會話
部署 Django
其它
其它核心功能
高級
Django中的密碼管理
模型元選項
按需內(nèi)容處理
查找 API 參考
高級
Django 的快捷函數(shù)
Django 的設(shè)置
Admin
開發(fā)過程
新手入門
基于類的視圖
模型實(shí)例參考
信號
表單素材 ( <code>Media</code> 類)
自定義查找
常見的網(wǎng)站應(yīng)用工具
模型
django.contrib.humanize
Django模版語言
點(diǎn)擊劫持保護(hù)
管理操作
編寫你的第一個 Django 程序 第2部分
Django安全
模式編輯器
多數(shù)據(jù)庫
部署
基于類的視圖
內(nèi)建的視圖
視圖裝飾器
面向設(shè)計師
編寫視圖
應(yīng)用程序
如何使用WSGI 部署
參考
表單 API
文件儲存API
認(rèn)證
國際化和本地化
錯誤報告
基礎(chǔ)
基礎(chǔ)
將遺留數(shù)據(jù)庫整合到Django
教程
Django異常
編寫你的第一個 Django 程序 第4部分
遷移
分頁
重定向應(yīng)用
表單
從零開始
為模型提供初始數(shù)據(jù)
設(shè)置
使用Django輸出CSV
關(guān)聯(lián)對象參考
使用表單
Django 中的用戶認(rèn)證
快速安裝指南
安全問題歸檔
數(shù)據(jù)庫函數(shù)
編寫自定義的django-admin命令
高級教程
管理文件
格式本地化
基于類的通用視圖 —— 索引
安全
系統(tǒng)檢查框架
為Django編寫首個補(bǔ)丁
模板層
Widgets
編寫你的第一個 Django 程序 第1部分
執(zhí)行查詢

URL調(diào)度器

簡潔、優(yōu)雅的URL 模式在高質(zhì)量的Web 應(yīng)用中是一個非常重要的細(xì)節(jié)。Django 允許你任意設(shè)計你的URL,不受框架束縛。

不要求有.php.cgi,更不會要求類似0,2097,1-1-1928,00 這樣無意義的東西。

參見萬維網(wǎng)的發(fā)明者Berners-Lee 的Cool URIs don’t change,里面有關(guān)于為什么URL 應(yīng)該保持整潔和有意義的卓越的論證。

概覽

為了給一個應(yīng)用設(shè)計URL,你需要創(chuàng)建一個Python 模塊,通常稱為URLconf(URL configuration)。這個模塊是純粹的Python 代碼,包含URL 模式(簡單的正則表達(dá)式)到Python 函數(shù)(你的視圖)的簡單映射。

映射可短可長,隨便你。它可以引用其它的映射。而且,因?yàn)樗羌兇獾腜ython 代碼,它可以動態(tài)構(gòu)造。

Django 還提供根據(jù)當(dāng)前語言翻譯URL 的一種方法。更多信息參見國際化文檔。

Django 如何處理一個請求

當(dāng)一個用戶請求Django 站點(diǎn)的一個頁面,下面是Django 系統(tǒng)決定執(zhí)行哪個Python 代碼使用的算法:

  1. Django 決定要使用的根URLconf 模塊。通常,這個值就是ROOT_URLCONF 的設(shè)置,但是如果進(jìn)來的HttpRequest 對象具有一個urlconf 屬性(通過中間件request processing 設(shè)置),則使用這個值來替換ROOT_URLCONF 設(shè)置。
  2. Django 加載該P(yáng)ython 模塊并尋找可用的urlpatterns。它是django.conf.urls.url() 實(shí)例的一個Python 列表。
  3. Django 依次匹配每個URL 模式,在與請求的URL 匹配的第一個模式停下來。
  4. 一旦其中的一個正則表達(dá)式匹配上,Django 將導(dǎo)入并調(diào)用給出的視圖,它是一個簡單的Python 函數(shù)(或者一個基于類的視圖)。視圖將獲得如下參數(shù):
    • 一個HttpRequest 實(shí)例。
    • 如果匹配的正則表達(dá)式?jīng)]有返回命名的組,那么正則表達(dá)式匹配的內(nèi)容將作為位置參數(shù)提供給視圖。
    • 關(guān)鍵字參數(shù)由正則表達(dá)式匹配的命名組組成,但是可以被django.conf.urls.url()的可選參數(shù)kwargs覆蓋。
  5. 如果沒有匹配到正則表達(dá)式,或者如果過程中拋出一個異常,Django 將調(diào)用一個適當(dāng)?shù)腻e誤處理視圖。請參見下面的錯誤處理。

例子

下面是一個簡單的 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 中捕獲一個值,只需要在它周圍放置一對圓括號。
  • 不需要添加一個前導(dǎo)的反斜杠,因?yàn)槊總€URL 都有。例如,應(yīng)該是^articles 而不是 ^/articles
  • 每個正則表達(dá)式前面的'r' 是可選的但是建議加上。它告訴Python 這個字符串是“原始的” —— 字符串中任何字符都不應(yīng)該轉(zhuǎn)義。參見Dive Into Python 中的解釋。

一些請求的例子:

  • /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調(diào)用函數(shù)views.month_archive(request, '2005', '03')。
  • /articles/2005/3/ 不匹配任何URL 模式,因?yàn)榱斜碇械牡谌齻€模式要求月份應(yīng)該是兩個數(shù)字。
  • /articles/2003/ 將匹配列表中的第一個模式不是第二個,因?yàn)槟J桨错樞蚱ヅ?,第一個會首先測試是否匹配。請像這樣自由插入一些特殊的情況來探測匹配的次序。
  • /articles/2003 不匹配任何一個模式,因?yàn)槊總€模式要求URL 以一個反斜線結(jié)尾。
  • /articles/2003/03/03/ 將匹配最后一個模式。Django 將調(diào)用函數(shù)views.article_detail(request, '2003', '03', '03')

命名組

上面的示例使用簡單的、沒有命名的正則表達(dá)式組(通過圓括號)來捕獲URL 中的值并以位置 參數(shù)傳遞給視圖。在更高級的用法中,可以使用命名的正則表達(dá)式組來捕獲URL 中的值并以關(guān)鍵字 參數(shù)傳遞給視圖。

在Python 正則表達(dá)式中,命名正則表達(dá)式組的語法是(?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),
]

這個實(shí)現(xiàn)與前面的示例完全相同,只有一個細(xì)微的差別:捕獲的值作為關(guān)鍵字參數(shù)而不是位置參數(shù)傳遞給視圖函數(shù)。例如:

  • /articles/2005/03/ 請求將調(diào)用views.month_archive(request, year='2005', month='03')函數(shù),而不是views.month_archive(request, '2005', '03')。
  • /articles/2003/03/03/ 請求將調(diào)用函數(shù)views.article_detail(request, year='2003', month='03', day='03')

在實(shí)際應(yīng)用中,這意味你的URLconf 會更加明晰且不容易產(chǎn)生參數(shù)順序問題的錯誤 —— 你可以在你的視圖函數(shù)定義中重新安排參數(shù)的順序。當(dāng)然,這些好處是以簡潔為代價;有些開發(fā)人員認(rèn)為命名組語法丑陋而繁瑣。

匹配/分組算法

下面是URLconf 解析器使用的算法,針對正則表達(dá)式中的命名組和非命名組:

  1. 如果有命名參數(shù),則使用這些命名參數(shù),忽略非命名參數(shù)。
  2. 否則,它將以位置參數(shù)傳遞所有的非命名參數(shù)。

根據(jù)傳遞額外的選項給視圖函數(shù)(下文),這兩種情況下,多余的關(guān)鍵字參數(shù)也將傳遞給視圖。

URLconf 在什么上查找

URLconf 在請求的URL 上查找,將它當(dāng)做一個普通的Python 字符串。不包括GET和POST參數(shù)以及域名。

例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/。

http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/。

URLconf 不檢查請求的方法。換句話講,所有的請求方法 —— 同一個URL的POST、GETHEAD等等 —— 都將路由到相同的函數(shù)。

捕獲的參數(shù)永遠(yuǎn)是字符串

每個捕獲的參數(shù)都作為一個普通的Python 字符串傳遞給視圖,無論正則表達(dá)式使用的是什么匹配方式。例如,下面這行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

... views.year_archive()year 參數(shù)將是一個字符串,即使[0-9]{4} 值匹配整數(shù)字符串。

指定視圖參數(shù)的默認(rèn)值

有一個方便的小技巧是指定視圖參數(shù)的默認(rèn)值。 下面是一個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() 函數(shù)將使用num參數(shù)的默認(rèn)值"1"。如果第二個模式匹配,page() 將使用正則表達(dá)式捕獲的num 值。

性能

urlpatterns 中的每個正則表達(dá)式在第一次訪問它們時被編譯。這使得系統(tǒng)相當(dāng)快。

urlpatterns 變量的語法

urlpatterns 應(yīng)該是url() 實(shí)例的一個Python 列表。

錯誤處理

當(dāng)Django 找不到一個匹配請求的URL 的正則表達(dá)式時,或者當(dāng)拋出一個異常時,Django 將調(diào)用一個錯誤處理視圖。

這些情況發(fā)生時使用的視圖通過4個變量指定。它們的默認(rèn)值應(yīng)該滿足大部分項目,但是通過賦值給它們以進(jìn)一步的自定義也是可以的。

完整的細(xì)節(jié)請參見自定義錯誤視圖

這些值可以在你的根URLconf 中設(shè)置。在其它URLconf 中設(shè)置這些變量將不會生效果。

它們的值必須是可調(diào)用的或者是表示視圖的Python 完整導(dǎo)入路徑的字符串,可以方便地調(diào)用它們來處理錯誤情況。

這些值是:

  • handler404 —— 參見django.conf.urls.handler404
  • handler500 —— 參見django.conf.urls.handler500。
  • handler403 —— 參見django.conf.urls.handler403。
  • handler400 —— 參見django.conf.urls.handler400。

包含其它的URLconfs

在任何時候,你的urlpatterns 都可以包含其它URLconf 模塊。這實(shí)際上將一部分URL 放置與其它URL 下面。

例如,下面是URLconf for the Django 網(wǎng)站自己的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 ...
]

注意,這個例子中的正則表達(dá)式?jīng)]有包含$(字符串結(jié)束匹配符),但是包含一個末尾的反斜杠。每當(dāng)Django 遇到include()django.conf.urls.include())時,它會去掉URL 中匹配的部分并將剩下的字符串發(fā)送給包含的URLconf 做進(jìn)一步處理。

另外一種包含其它URL 模式的方式是使用一個url() 實(shí)例的列表。例如,請看下面的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 中的冗余,其中某個模式前綴被重復(fù)使用。例如,考慮這個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),
]

我們可以改進(jìn)它,通過只聲明共同的路徑前綴一次并將后面的部分分組:

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),
    ])),
]

捕獲的參數(shù)

被包含的URLconf 會收到來之父URLconf 捕獲的任何參數(shù),所以下面的例子是合法的:

# 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。

嵌套的參數(shù)

正則表達(dá)式允許嵌套的參數(shù),Django 將解析它們并傳遞給視圖。當(dāng)反查時,Django 將嘗試填滿所有外圍捕獲的參數(shù),并忽略嵌套捕獲的參數(shù)??紤]下面的URL 模式,它帶有一個可選的page 參數(shù):

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
]

兩個模式都使用嵌套的參數(shù),其解析方式是:例如blog/page-2/ 將匹配blog_articles并帶有兩個位置參數(shù)page-2/ 和2。第二個comments 的模式將匹配comments/page-2/ 并帶有一個值為2 的關(guān)鍵字參數(shù)page_number。這個例子中外圍參數(shù)是一個不捕獲的參數(shù)(?:...)

blog_articles 視圖需要最外層捕獲的參數(shù)來反查,在這個例子中是page-2/或者沒有參數(shù),而comments可以不帶參數(shù)或者用一個page_number值來反查。

嵌套捕獲的參數(shù)使得視圖參數(shù)和URL 之間存在強(qiáng)耦合,正如blog_articles 所示:視圖接收URL(page-2/)的一部分,而不只是視圖感興趣的值。這種耦合在反查時更加顯著,因?yàn)榉床橐晥D時我們需要傳遞URL 的一個片段而不只是page 的值。

作為一個經(jīng)驗(yàn)的法則,當(dāng)正則表達(dá)式需要一個參數(shù)但視圖忽略它的時候,只捕獲視圖需要的值并使用非捕獲參數(shù)。

傳遞額外的選項給視圖函數(shù)

URLconfs 具有一個鉤子,讓你傳遞一個Python 字典作為額外的參數(shù)傳遞給視圖函數(shù)。

django.conf.urls.url() 函數(shù)可以接收一個可選的第三個參數(shù),它是一個字典,表示想要傳遞給視圖函數(shù)的額外關(guān)鍵字參數(shù)。

例如:

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 將調(diào)用views.year_archive(request, year='2005', foo='bar')。

這個技術(shù)在Syndication 框架 中使用,來傳遞元數(shù)據(jù)和選項給視圖。

處理沖突

URL 模式捕獲的命名關(guān)鍵字參數(shù)和在字典中傳遞的額外參數(shù)有可能具有相同的名稱。當(dāng)這種情況發(fā)生時,將使用字典中的參數(shù)而不是URL 中捕獲的參數(shù)。

傳遞額外的選項給include()

類似地,你可以傳遞額外的選項給include()。當(dāng)你傳遞額外的選項給include() 時,被包含的URLconf 的每一 行將被傳遞這些額外的選項。

例如,下面兩個URLconf 設(shè)置功能上完全相同:

設(shè)置一次:

# 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),
]

設(shè)置兩次:

# 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}),
]

注意,額外的選項將永遠(yuǎn)傳遞給被包含的URLconf 中的每一行,無論該行的視圖實(shí)際上是否認(rèn)為這些選項是合法的。由于這個原因,該技術(shù)只有當(dāng)你確定被包含的URLconf 中的每個視圖都接收你傳遞給它們的額外的選項。

URL 的反向解析

在使用Django 項目時,一個常見的需求是獲得URL 的最終形式,以用于嵌入到生成的內(nèi)容中(視圖中和顯示給用戶的URL等)或者用于處理服務(wù)器端的導(dǎo)航(重定向等)。

人們強(qiáng)烈希望不要硬編碼這些URL(費(fèi)力、不可擴(kuò)展且容易產(chǎn)生錯誤)或者設(shè)計一種與URLconf 毫不相關(guān)的專門的URL 生成機(jī)制,因?yàn)檫@樣容易導(dǎo)致一定程度上產(chǎn)生過期的URL。

換句話講,需要的是一個DRY 機(jī)制。除了其它有點(diǎn),它還允許設(shè)計的URL 可以自動更新而不用遍歷項目的源代碼來搜索并替換過期的URL。

獲取一個URL 最開始想到的信息是處理它視圖的標(biāo)識(例如名字),查找正確的URL 的其它必要的信息有視圖參數(shù)的類型(位置參數(shù)、關(guān)鍵字參數(shù))和值。

Django 提供一個辦法是讓URL 映射是URL 設(shè)計唯一的地方。你填充你的URLconf,然后可以雙向使用它:

  • 根據(jù)用戶/瀏覽器發(fā)起的URL 請求,它調(diào)用正確的Django 視圖,并從URL 中提取它的參數(shù)需要的值。
  • 根據(jù)Django 視圖的標(biāo)識和將要傳遞給它的參數(shù)的值,獲取與之關(guān)聯(lián)的URL。

第一種方式是我們在前面的章節(jié)中一直討論的用法。第二種方式叫做反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。

在需要URL 的地方,對于不同層級,Django 提供不同的工具用于URL 反查:

  • 在模板中:使用url 模板標(biāo)簽。
  • 在Python 代碼中:使用django.core.urlresolvers.reverse() 函數(shù)。
  • 在更高層的與處理Django 模型實(shí)例相關(guān)的代碼中:使用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'),
    #...
]

根據(jù)這里的設(shè)計,某一年nnnn對應(yīng)的歸檔的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,)))

如果出于某種原因決定按年歸檔文章發(fā)布的URL應(yīng)該調(diào)整一下,那么你將只需要修改URLconf 中的內(nèi)容。

在某些場景中,一個視圖是通用的,所以在URL 和視圖之間存在多對一的關(guān)系。對于這些情況,當(dāng)反查URL 時,只有視圖的名字還不夠。請閱讀下一節(jié)來了解Django 為這個問題提供的解決辦法。

命名URL 模式

為了完成上面例子中的URL 反查,你將需要使用命名的URL 模式。URL 的名稱使用的字符串可以包含任何你喜歡的字符。不只限制在合法的Python 名稱。

當(dāng)命名你的URL 模式時,請確保使用的名稱不會與其它應(yīng)用中名稱沖突。如果你的URL 模式叫做comment,而另外一個應(yīng)用中也有一個同樣的名稱,當(dāng)你在模板中使用這個名稱的時候不能保證將插入哪個URL。

在URL 名稱中加上一個前綴,比如應(yīng)用的名稱,將減少沖突的可能。我們建議使用myapp-comment 而不是comment。

URL 命名空間

簡介

URL 命名空間允許你反查到唯一的命名URL 模式,即使不同的應(yīng)用使用相同的URL 名稱。第三方應(yīng)用始終使用帶命名空間的URL 是一個很好的實(shí)踐(我們在教程中也是這么做的)。類似地,它還允許你在一個應(yīng)用有多個實(shí)例部署的情況下反查URL。換句話講,因?yàn)橐粋€應(yīng)用的多個實(shí)例共享相同的命名URL,命名空間將提供一種區(qū)分這些命名URL 的方法。

在一個站點(diǎn)上,正確使用URL 命名空間的Django 應(yīng)用可以部署多次。例如,django.contrib.admin 具有一個AdminSite 類,它允許你很容易地部署多個管理站點(diǎn)的實(shí)例。在下面的例子中,我們將討論在兩個不同的地方部署教程中的polls 應(yīng)用,這樣我們可以為兩種不同的用戶(作者和發(fā)布者)提供相同的功能。

一個URL 命名空間有兩個部分,它們都是字符串:

應(yīng)用命名空間

它表示正在部署的應(yīng)用的名稱。一個應(yīng)用的每個實(shí)例具有相同的應(yīng)用命名空間。例如,可以預(yù)見Django 的管理站點(diǎn)的應(yīng)用命名空間是'admin'。

實(shí)例命名空間

它表示應(yīng)用的一個特定的實(shí)例。實(shí)例的命名空間在你的全部項目中應(yīng)該是唯一的。但是,一個實(shí)例的命名空間可以和應(yīng)用的命名空間相同。它用于表示一個應(yīng)用的默認(rèn)實(shí)例。例如,Django 管理站點(diǎn)實(shí)例具有一個默認(rèn)的實(shí)例命名空間'admin'。 URL 的命名空間使用':' 操作符指定。例如,管理站點(diǎn)應(yīng)用的主頁使用'admin:index'。它表示'admin' 的一個命名空間和'index' 的一個命名URL。

命名空間也可以嵌套。命名URL'sports:polls:index' 將在命名空間'polls'中查找'index',而poll 定義在頂層的命名空間'sports' 中。

反查帶命名空間的URL

當(dāng)解析一個帶命名空間的URL(例如'polls:index')時,Django 將切分名稱為多個部分,然后按下面的步驟查找:

  1. 首先,Django 查找匹配的應(yīng)用的命名空間(在這個例子中為'polls')。這將得到該應(yīng)用實(shí)例的一個列表。

  2. 如果有定義當(dāng)前 應(yīng)用,Django 將查找并返回那個實(shí)例的URL 解析器。當(dāng)前 應(yīng)用可以通過請求上的一個屬性指定。希望可以多次部署的應(yīng)用應(yīng)該設(shè)置正在處理的request上的current_app 屬性。
Changed in Django 1.8:

在以前版本的Django 中,你必須在用于渲染模板的每個`Context` 或 `RequestContext`上設(shè)置`current_app` 屬性。

當(dāng)前應(yīng)用還可以通過reverse() 函數(shù)的一個參數(shù)手工設(shè)定。

  1. 如果沒有當(dāng)前應(yīng)用。Django 將查找一個默認(rèn)的應(yīng)用實(shí)例。默認(rèn)的應(yīng)用實(shí)例是實(shí)例命名空間應(yīng)用命名空間 一致的那個實(shí)例(在這個例子中,polls 的一個叫做'polls' 的實(shí)例)。

  2. 如果沒有默認(rèn)的應(yīng)用實(shí)例,Django 將該應(yīng)用挑選最后部署的實(shí)例,不管實(shí)例的名稱是什么。

  3. 如果提供的命名空間與第1步中的應(yīng)用命名空間 不匹配,Django 將嘗試直接將此命名空間作為一個實(shí)例命名空間查找。

如果有嵌套的命名空間,將為命名空間的每個部分重復(fù)調(diào)用這些步驟直至剩下視圖的名稱還未解析。然后該視圖的名稱將被解析到找到的這個命名空間中的一個URL。

例子

為了演示解析的策略,考慮教程中polls 應(yīng)用的兩個實(shí)例:'author-polls' 和'publisher-polls'。假設(shè)我們已經(jīng)增強(qiáng)了該應(yīng)用,在創(chuàng)建和顯示投票時考慮了實(shí)例命名空間。

#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'),
    ...
]

根據(jù)以上設(shè)置,可以使用下面的查詢:

  • 如果其中一個實(shí)例是當(dāng)前實(shí)例 —— 如果我們正在渲染'author-polls' 實(shí)例的detail 頁面 —— 'polls:index' 將解析成'author-polls' 實(shí)例的主頁面;例如下面兩個都將解析成"/author-polls/"。

在基于類的視圖的方法中:

reverse('polls:index', current_app=self.request.resolver_match.namespace)

和在模板中:

{% url 'polls:index' %}

注意,在模板中的反查需要添加requestcurrent_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)
  • 如果沒有當(dāng)前實(shí)例 —— 如果我們在站點(diǎn)的其它地方渲染一個頁面 —— 'polls:index' 將解析到最后注冊的polls的一個實(shí)例。因?yàn)闆]有默認(rèn)的實(shí)例(命名空間為'polls'的實(shí)例),將使用注冊的polls 的最后一個實(shí)例。它將是'publisher-polls',因?yàn)樗窃?code>urlpatterns中最后一個聲明的。
  • 'author-polls:index' 將永遠(yuǎn)解析到 'author-polls' 實(shí)例的主頁('publisher-polls' 類似)。

如果還有一個默認(rèn)的實(shí)例 —— 例如,一個名為'polls' 的實(shí)例 —— 上面例子中唯一的變化是當(dāng)沒有當(dāng)前實(shí)例的情況(上述第二種情況)。在這種情況下 'polls:index' 將解析到默認(rèn)實(shí)例而不是urlpatterns 中最后聲明的實(shí)例的主頁。

URL 命名空間和被包含的URLconf

被包含的URLconf 的命名空間可以通過兩種方式指定。

首先,在你構(gòu)造你的URL 模式時,你可以提供 應(yīng)用 和 實(shí)例的命名空間給include() 作為參數(shù)。例如:

url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')),

這將包含polls.urls 中定義的URL 到應(yīng)用命名空間 'polls'中,其實(shí)例命名空間為'author-polls'。

其次,你可以include 一個包含嵌套命名空間數(shù)據(jù)的對象。如果你include() 一個url() 實(shí)例的列表,那么該對象中包含的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 模式到給定的應(yīng)用和實(shí)例命名空間中。

例如,Django 的管理站點(diǎn)部署的實(shí)例叫AdminSiteAdminSite 對象具有一個urls 屬性:一個3元組,包含管理站點(diǎn)中的所有URL 模式和應(yīng)用的命名空間'admin'以及管理站點(diǎn)實(shí)例的名稱。你include()到你項目的urlpatterns 中的是這個urls 屬性。

請確保傳遞一個元組給include()。如果你只是傳遞3個參數(shù):include(polls_patterns, 'polls', 'author-polls'),Django 不會拋出一個錯誤,但是根據(jù)include() 的功能,'polls' 將是實(shí)例的命名空間而'author-polls' 將是應(yīng)用的命名空間,而不是反過來的。

譯者:Django 文檔協(xié)作翻譯小組,原文:URLconfs。

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。

{% endraw %}

上一篇:分頁下一篇:模式編輯器