Django 處理HTTP請求

2021-10-20 18:24 更新

URL調(diào)度

干凈,優(yōu)雅的URL方案是高質(zhì)量Web應(yīng)用程序中的重要細節(jié)。Django允許您根據(jù)需要設(shè)計URL,而無框架限制。

萬維網(wǎng)創(chuàng)建者蒂姆·伯納斯-李(Tim Berners-Lee)的文章“ Cool URIs not not change”中有關(guān)為什么URL應(yīng)該干凈和可用的出色論據(jù),請參見。

概述

要設(shè)計應(yīng)用程序的URL,您可以創(chuàng)建一個非正式地稱為URLconf(URL配置)的Python模塊 。該模塊是純Python代碼,并且是URL路徑表達式到Python函數(shù)(您的視圖)之間的映射。

該映射可以根據(jù)需要短或長。它可以引用其他映射。而且,由于它是純Python代碼,因此可以動態(tài)構(gòu)建。

Django還提供了一種根據(jù)活動語言翻譯URL的方法。有關(guān)更多信息,請參見國際化文檔。

Django是如何處理一個請求

當(dāng)用戶從您的Django支持的網(wǎng)站請求頁面時,系統(tǒng)將使用以下算法來確定要執(zhí)行的Python代碼:

  1. Django確定要使用的根URLconf模塊。通常,這是ROOT_URLCONF設(shè)置的值,但是如果傳入 HttpRequest對象具有urlconf 屬性(由中間件設(shè)置),則將使用其值代替 ROOT_URLCONF設(shè)置。
  2. Django加載該Python模塊并查找變量 urlpatterns。這應(yīng)該是一個序列的 django.urls.path()和/或django.urls.re_path()實例。
  3. Django按順序遍歷每個URL模式,并在第一個與請求的URL匹配的URL處停止,與匹配 path_info。
  4. 一旦其中一個URL模式匹配,Django就會導(dǎo)入并調(diào)用給定的視圖,該視圖是Python函數(shù)(或基于類的視圖)。該視圖將傳遞以下參數(shù):的實例HttpRequest。如果匹配的URL模式不包含命名組,則來自正則表達式的匹配項將作為位置參數(shù)提供。關(guān)鍵字參數(shù)由提供的路徑表達式匹配的任何命名部分組成,這些名稱部分由或 的可選kwargs參數(shù)中指定的任何參數(shù)覆蓋。django.urls.path()django.urls.re_path()在Django 3.0中進行了更改:在舊版本中,帶有None值的關(guān)鍵字參數(shù)也由未提供的命名部分組成。
  5. 如果沒有URL模式匹配,或者在此過程中的任何時候引發(fā)異常,Django都會調(diào)用一個適當(dāng)?shù)腻e誤處理視圖。請參閱下面的錯誤處理。

例子

這是一個示例URLconf:

from django.urls import path
?
from . import views
?
urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  path('articles/<int:year>/', views.year_archive),
  path('articles/<int:year>/<int:month>/', views.month_archive),
  path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

筆記:

  • 要從URL捕獲值,請使用尖括號。
  • 捕獲的值可以選擇包括轉(zhuǎn)換器類型。例如,用于 `捕獲整數(shù)參數(shù)。如果不包括轉(zhuǎn)換器/`,則匹配除字符以外的任何字符串。
  • 無需添加斜杠,因為每個URL都有該斜杠。例如articles,不是/articles。

請求示例:

  • 請求/articles/2005/03/匹配列表中的第三個條目。Django將調(diào)用該函數(shù) 。views.month_archive(request, year=2005, month=3)
  • /articles/2003/會匹配列表中的第一個模式,而不是第二個,因為這些模式是按順序測試的,而第一個是第一個通過的測試。隨意利用命令來插入類似這樣的特殊情況。在這里,Django將調(diào)用該函數(shù) views.special_case_2003(request)
  • /articles/2003 不會與任何這些模式匹配,因為每種模式都要求URL以斜杠結(jié)尾。
  • /articles/2003/03/building-a-django-site/將匹配最終模式。Django將調(diào)用該函數(shù) 。views.article_detail(request, year=2003, month=3, slug="building-a-django-site")

路徑轉(zhuǎn)換器

默認情況下,以下路徑轉(zhuǎn)換器可用:

  • str-匹配任何非空字符串,但路徑分隔符除外'/'。如果表達式中不包含轉(zhuǎn)換器,則為默認設(shè)置。
  • int-匹配零或任何正整數(shù)。返回int。
  • slug-匹配由ASCII字母或數(shù)字以及連字符和下劃線字符組成的任何條形字符串。例如, building-your-1st-django-site。
  • uuid-匹配格式化的UUID。為防止多個URL映射到同一頁面,必須包含破折號,并且字母必須小寫。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一個 UUID實例。
  • path-匹配任何非空字符串,包括路徑分隔符 '/'。這樣,您就可以匹配完整的URL路徑,而不是像一樣匹配URL路徑的一部分str。

注冊自定義路徑轉(zhuǎn)換器

對于更復(fù)雜的匹配要求,您可以定義自己的路徑轉(zhuǎn)換器。

轉(zhuǎn)換器是包含以下內(nèi)容的類:

  • 一regex類屬性,作為一個字符串。
  • 一種方法,用于將匹配的字符串轉(zhuǎn)換為應(yīng)傳遞給視圖函數(shù)的類型。如果無法轉(zhuǎn)換給定值,則應(yīng)加注。A 被解釋為不匹配,結(jié)果404響應(yīng)會發(fā)送給用戶,除非另一個URL模式匹配。to_python(self, value)``ValueError``ValueError
  • 一種方法,用于將Python類型轉(zhuǎn)換為要在URL中使用的字符串。to_url(self, value)

例如:

class FourDigitYearConverter:
  regex = '[0-9]{4}'
?
  def to_python(self, value):
      return int(value)
?
  def to_url(self, value):
      return '%04d' % value

使用register_converter()以下命令在URLconf中注冊自定義轉(zhuǎn)換器類 :

from django.urls import path, register_converter
?
from . import converters, views
?
register_converter(converters.FourDigitYearConverter, 'yyyy')
?
urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  path('articles/<yyyy:year>/', views.year_archive),
  ...
]

使用正則表達式

如果路徑和轉(zhuǎn)換器語法不足以定義URL模式,則還可以使用正則表達式。為此,請使用 re_path()代替path()

在Python正則表達式中,命名正則表達式組的語法為(?Ppattern),其中name是組的名稱,并且 pattern是匹配的某種模式。

這是前面的示例URLconf,使用正則表達式重寫:

from django.urls import path, re_path
?
from . import views
?
urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
  re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
  re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

這可以完成與上一個示例大致相同的操作,除了:

  • 將要匹配的確切URL受到更多限制。例如,年份10000將不再匹配,因為年份整數(shù)被限制為正好是四位數(shù)長。
  • 無論正則表達式進行哪種匹配,每個捕獲的參數(shù)都將作為字符串發(fā)送到視圖。

當(dāng)從使用切換為使用path(), re_path()反之亦然時,特別重要的是要注意視圖參數(shù)的類型可能會更改,因此您可能需要調(diào)整視圖。

使用未命名的正則表達式組

除了命名組語法(例如)之外(?P[0-9]{4}),您還可以使用較短的未命名組(例如)([0-9]{4})。

不建議特別使用此用法,因為這樣可以更輕松地在匹配的預(yù)期含義和視圖的參數(shù)之間意外引入錯誤。

無論哪種情況,建議在給定的正則表達式中僅使用一種樣式。當(dāng)兩種樣式混合使用時,任何未命名的組都會被忽略,只有命名的組才會傳遞給視圖函數(shù)。

嵌套參數(shù)

正則表達式允許嵌套參數(shù),而Django會解析它們并將其傳遞給視圖。反轉(zhuǎn)時,Django將嘗試填寫所有外部捕獲的參數(shù),而忽略任何嵌套的捕獲參數(shù)。考慮以下URL模式,這些URL模式可以選擇采用page參數(shù):

from django.urls import re_path
?
urlpatterns = [
  re_path(r'^blog/(page-(\d+)/)?$', blog_articles),                 # bad
  re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]

兩種模式都使用嵌套參數(shù),并將解析:例如, blog/page-2/將導(dǎo)致與匹配blog_articles兩個位置參數(shù):page-2/和2。的第二個模式 comments將comments/page-2/與關(guān)鍵字參數(shù) page_number設(shè)置為2 匹配。在這種情況下,外部參數(shù)是一個非捕獲參數(shù)(?:...)。

該blog_articles視圖需要最外層捕獲的參數(shù)被反轉(zhuǎn),page-2/或者在這種情況下不需要參數(shù),而視圖 comments可以不帶參數(shù)也沒有值而被反轉(zhuǎn)page_number。

嵌套的捕獲參數(shù)在視圖參數(shù)和URL之間建立了牢固的耦合,如下所示blog_articles:視圖接收部分URL(page-2/),而不是僅接收視圖感興趣的值。這種反轉(zhuǎn)在反轉(zhuǎn)時更為明顯,因為反轉(zhuǎn)視圖,我們需要傳遞該URL而不是頁碼。

根據(jù)經(jīng)驗,當(dāng)正則表達式需要參數(shù)但視圖將其忽略時,僅捕獲視圖需要使用的值,并使用非捕獲參數(shù)。

URLconf搜索的內(nèi)容

URLconf按照正常的Python字符串搜索請求的URL。這不包括GET或POST參數(shù)或域名。

例如,在對的請求中https://www.example.com/myapp/,URLconf將尋找myapp/。

在請求中https://www.example.com/myapp/?page=3,URLconf將尋找myapp/。

URLconf不會查看請求方法。換句話說,所有的請求方法- ,,POST 等-將被路由到相同的URL相同的功能。GET``HEAD

為視圖參數(shù)指定默認值

一個方便的技巧是為視圖的參數(shù)指定默認參數(shù)。這是一個示例URLconf和視圖:

# URLconf
from django.urls import path
?
from . import views
?
urlpatterns = [
  path('blog/', views.page),
  path('blog/page<int:num>/', 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中捕獲任何內(nèi)容。如果第一個模式匹配,該page()函數(shù)將使用它的默認參數(shù)num,1。如果第二個模式匹配, page()將使用num捕獲的任何值。

性能

中的每個正則表達式urlpatterns都是在首次訪問時進行編譯。這使系統(tǒng)運行起來非??臁?/p>

在語法urlpatterns變量

urlpatterns應(yīng)該是一個序列的path() 和/或re_path()實例。

錯誤處理

當(dāng)Django無法找到所請求URL的匹配項或引發(fā)異常時,Django會調(diào)用錯誤處理視圖。

這些情況下使用的視圖由四個變量指定。它們的默認值足以滿足大多數(shù)項目的需要,但可以通過覆蓋其默認值來進行進一步的自定義。

有關(guān)完整的詳細信息,請參見有關(guān)自定義錯誤視圖的文檔。

可以在您的根URLconf中設(shè)置這些值。在任何其他URLconf中設(shè)置這些變量將無效。

值必須是可調(diào)用的,或者是表示視圖的完整Python導(dǎo)入路徑的字符串,應(yīng)該調(diào)用該視圖來處理當(dāng)前的錯誤情況。

變量是:

包括其他的URLconf 

在任何時候,您urlpatterns都可以“包括”其他URLconf模塊。實質(zhì)上,這會將“ URL”“植根”在其他URL之下。

例如,這是Django網(wǎng)站 本身的URLconf的摘錄。它包括許多其他URLconf:

from django.urls import include, path
?
urlpatterns = [
  # ... snip ...
  path('community/', include('aggregator.urls')),
  path('contact/', include('contact.urls')),
  # ... snip ...
]

每當(dāng)Django遇到時include(),它都會截斷直到該時間點匹配的URL的任何部分,并將剩余的字符串發(fā)送到包含的URLconf中以進行進一步處理。

另一種可能性是通過使用path()實例列表包括其他URL模式 。例如,考慮以下URLconf:

from django.urls import include, path
?
from apps.main import views as main_views
from credit import views as credit_views
?
extra_patterns = [
  path('reports/', credit_views.report),
  path('reports/<int:id>/', credit_views.report),
  path('charge/', credit_views.charge),
]
?
urlpatterns = [
  path('', main_views.homepage),
  path('help/', include('apps.help.urls')),
  path('credit/', include(extra_patterns)),
]

在此示例中,/credit/reports/URL將由credit_views.report()Django視圖處理 。

這可用于從URLconf中刪除重復(fù)使用單個模式前綴的冗余。例如,考慮以下URLconf:

from django.urls import path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/history/', views.history),
    path('<page_slug>-<page_id>/edit/', views.edit),
    path('<page_slug>-<page_id>/discuss/', views.discuss),
    path('<page_slug>-<page_id>/permissions/', views.permissions),
]

我們可以通過只聲明一次公共路徑前綴并對不同的后綴進行分組來改善這一點:

from django.urls import include, path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/', include([
        path('history/', views.history),
        path('edit/', views.edit),
        path('discuss/', views.discuss),
        path('permissions/', views.permissions),
    ])),
]

捕捉的參數(shù)

包含的URLconf從父URLconfs接收任何捕獲的參數(shù),因此以下示例有效:

# In settings/urls/main.py
from django.urls import include, path

urlpatterns = [
    path('<username>/blog/', include('foo.urls.blog')),
]

# In foo/urls/blog.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.blog.index),
    path('archive/', views.blog.archive),
]

在上面的示例中,捕獲的"username"變量按預(yù)期傳遞給包含的URLconf。

傳遞額外的選項來查看函數(shù)

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

path()函數(shù)可以使用可選的第三個參數(shù),該參數(shù)應(yīng)該是傳遞給view函數(shù)的額外關(guān)鍵字參數(shù)的字典。

例如:

from django.urls import path
from . import views

urlpatterns = [
    path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]

在此示例中,對于的請求/blog/2005/,Django將調(diào)用 。views.year_archive(request, year=2005, foo='bar')

該技術(shù)在 聯(lián)合框架中用于將元數(shù)據(jù)和選項傳遞給視圖。

處理沖突

URL模式可能會捕獲命名的關(guān)鍵字參數(shù),并在其額外參數(shù)字典中傳遞具有相同名稱的參數(shù)。發(fā)生這種情況時,將使用字典中的參數(shù)代替URL中捕獲的參數(shù)。

將額外的選項傳遞給include()

同樣,您可以將額外選項傳遞給include(),所包含的URLconf中的每一行都將傳遞額外選項。

例如,這兩個URLconf集在功能上是相同的:

設(shè)置一:

# main.py
from django.urls import include, path

urlpatterns = [
    path('blog/', include('inner'), {'blog_id': 3}),
]

# inner.py
from django.urls import path
from mysite import views

urlpatterns = [
    path('archive/', views.archive),
    path('about/', views.about),
]

設(shè)置二:

# main.py
from django.urls import include, path
from mysite import views

urlpatterns = [
    path('blog/', include('inner')),
]

# inner.py
from django.urls import path

urlpatterns = [
    path('archive/', views.archive, {'blog_id': 3}),
    path('about/', views.about, {'blog_id': 3}),
]

請注意,無論行的視圖是否實際接受這些選項,額外的選項將始終傳遞到所包含的URLconf中的每一行。因此,僅當(dāng)您確定所包含的URLconf中的每個視圖都接受要傳遞的額外選項時,此技術(shù)才有用。

URL的反向解析

在Django項目上進行工作時,通常需要獲取最終形式的URL,以嵌入生成的內(nèi)容(視圖和資產(chǎn)URL,向用戶顯示的URL等)或在服務(wù)器上處理導(dǎo)航流程側(cè)面(重定向等)

強烈希望避免對這些URL進行硬編碼(一種費力,不可擴展且易于出錯的策略)。同樣危險的是,設(shè)計臨時機制來生成與URLconf描述的設(shè)計平行的URL,這可能導(dǎo)致URL的生成隨著時間的推移而變得陳舊。

換句話說,需要一種DRY機制。除其他優(yōu)點外,它還允許URL設(shè)計的發(fā)展,而不必遍歷所有項目源代碼來搜索和替換過時的URL。

我們可以獲得URL的主要信息是負責(zé)處理它的視圖的標(biāo)識(例如名稱)。視圖參數(shù)的類型(位置,關(guān)鍵字)和值還必須包含在正確的URL查找中的其他信息。

Django提供了一個解決方案,使得URL映射器是URL設(shè)計的唯一存儲庫。您將其與URLconf一起提供,然后可以在兩個方向上使用它:

  • 從用戶/瀏覽器請求的URL開始,它將調(diào)用正確的Django視圖,以提供可能需要的任何參數(shù)以及從URL中提取的值。
  • 從標(biāo)識相應(yīng)的Django視圖以及將傳遞給該視圖的參數(shù)值開始,獲取關(guān)聯(lián)的URL。

第一個是我們在上一節(jié)中討論的用法。第二種是所謂的URL反向解析,反向URL匹配,反向URL查找或簡稱URL反向。

Django提供了執(zhí)行URL反轉(zhuǎn)的工具,這些工具與需要URL的不同層相匹配:

  • 在模板中:使用url模板標(biāo)記。
  • 在Python代碼中:使用reverse()函數(shù)。
  • 與Django模型實例的URL處理相關(guān)的高級代碼:get_absolute_url()方法。

例子

再次考慮以下URLconf條目:

from django.urls import path

from . import views

urlpatterns = [
    #...
    path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
    #...
]

根據(jù)這種設(shè)計,對應(yīng)于年度歸檔文件的URL NNNN 是/articles//。

您可以使用以下模板代碼獲取它們:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

或在Python代碼中:

from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

如果出于某種原因決定更改發(fā)布年度文章存檔內(nèi)容的URL,則只需要更改URLconf中的條目即可。

在視圖具有一般性質(zhì)的某些情況下,URL和視圖之間可能存在多對一關(guān)系。對于這些情況,在反向URL時,視圖名稱并不是一個足夠好的標(biāo)識符。閱讀下一節(jié)以了解Django為此提供的解決方案。

命名URL模式

為了執(zhí)行URL反向,您需要 像上面的示例一樣使用命名的URL模式。URL名稱使用的字符串可以包含您喜歡的任何字符。您不限于有效的Python名稱。

在命名URL模式時,請選擇不太可能與其他應(yīng)用程序的名稱沖突的名稱。如果調(diào)用URL模式,comment 而另一個應(yīng)用程序執(zhí)行相同的操作,則reverse()找到的URL 取決于項目urlpatterns列表中最后一個模式。

在您的URL名稱上添加前綴(可能源自應(yīng)用程序名稱(例如myapp-comment而不是comment)),可以減少發(fā)生沖突的機會。

如果要覆蓋視圖,可以故意選擇與另一個應(yīng)用程序相同的URL名稱。例如,一個常見的用例是覆蓋 LoginView。Django和大多數(shù)第三方應(yīng)用程序的某些部分假定此視圖具有名稱為的URL模式 login。如果你有一個自定義登錄查看,并給它的URL的名字login, reverse()會發(fā)現(xiàn)自定義視圖,只要它在 urlpatterns以后django.contrib.auth.urls包括(如果這是包含在所有)。

如果多個URL模式的參數(shù)不同,也可以使用相同的名稱。除URL名稱外,還要reverse() 匹配參數(shù)數(shù)量和關(guān)鍵字參數(shù)的名稱。

URL命名空間

簡介

URL名稱空間允許您唯一地反向命名URL模式,即使不同的應(yīng)用程序使用相同的URL名稱。對于第三方應(yīng)用程序,始終使用命名空間的URL是一個好習(xí)慣(就像我們在本教程中所做的那樣)。同樣,如果部署了一個應(yīng)用程序的多個實例,它還允許您反向URL。換句話說,由于單個應(yīng)用程序的多個實例將共享命名URL,因此名稱空間提供了一種區(qū)分這些命名URL的方法。

對于特定站點,可以多次使用正確使用URL名稱空間的Django應(yīng)用程序。例如,django.contrib.admin 有一AdminSite類允許您 部署多個admin實例。在下一個示例中,我們將討論從教程在兩個不同位置部署民意調(diào)查應(yīng)用程序的想法,以便我們可以為兩個不同的受眾(作者和發(fā)布者)提供相同的功能。

URL名稱空間分為兩部分,都是字符串:

  • 應(yīng)用程序名稱空間這描述了正在部署的應(yīng)用程序的名稱。單個應(yīng)用程序的每個實例將具有相同的應(yīng)用程序名稱空間。例如,Django的admin應(yīng)用程序具有可預(yù)測的應(yīng)用程序名稱空間'admin'。
  • 實例名稱空間這標(biāo)識了應(yīng)用程序的特定實例。實例名稱空間在整個項目中應(yīng)該是唯一的。但是,實例名稱空間可以與應(yīng)用程序名稱空間相同。這用于指定應(yīng)用程序的默認實例。例如,默認Django管理實例的實例名稱空間為'admin'。

使用':'操作符指定以名稱分隔的URL 。例如,使用引用管理應(yīng)用程序的主索引頁面'admin:index'。這表示的命名空間'admin',以及的命名URL 'index'。

命名空間也可以嵌套。命名的URL 'sports:polls:index'將尋找'index'在命名空間中命名的模式,該模式'polls'本身是在頂級命名空間中定義的'sports'。

反向命名空間的URL

給定'polls:index'要解析的命名空間URL(例如)后,Django會將完全限定的名稱拆分為多個部分,然后嘗試以下查找:

  1. 首先,Django尋找匹配的應(yīng)用程序名稱空間(在本示例中為'polls')。這將產(chǎn)生該應(yīng)用程序?qū)嵗牧斜怼?/li>
  2. 如果定義了當(dāng)前應(yīng)用程序,則Django查找并返回該實例的URL解析器??梢允褂?函數(shù)的current_app參數(shù)指定當(dāng)前應(yīng)用程序reverse()。該url模板標(biāo)簽使用當(dāng)前解決視圖在當(dāng)前應(yīng)用程序的命名空間 RequestContext。您可以通過在request.current_app屬性上設(shè)置當(dāng)前應(yīng)用程序來覆蓋此默認設(shè)置。
  3. 如果沒有當(dāng)前應(yīng)用程序,則Django將查找默認應(yīng)用程序?qū)嵗?。默認的應(yīng)用程序?qū)嵗蔷哂性搶嵗龑嵗臻g匹配應(yīng)用的命名空間(在此示例中,的一個實例polls稱為'polls')。
  4. 如果沒有默認應(yīng)用程序?qū)嵗?,則Django將選擇該應(yīng)用程序的最后部署實例,無論其實例名稱是什么。
  5. 如果在步驟1中提供的名稱空間與應(yīng)用程序名稱空間不匹配,Django將嘗試直接查找該名稱空間作為 實例名稱空間。

如果存在嵌套的名稱空間,則對名稱空間的每個部分重復(fù)這些步驟,直到僅解析視圖名稱為止。然后,將視圖名稱解析為找到的名稱空間中的URL。

例子

為了展示該解決方案的實際作用,請考慮polls本教程中應(yīng)用程序的兩個實例的示例:一個稱為'author-polls' ,一個稱為'publisher-polls'。假設(shè)我們已經(jīng)增強了該應(yīng)用程序,以便在創(chuàng)建和顯示民意測驗時考慮實例名稱空間。

的urls.py 

from django.urls import include, path

urlpatterns = [
    path('author-polls/', include('polls.urls', namespace='author-polls')),
    path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]

民調(diào)/的urls.py 

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]

使用此設(shè)置,可以進行以下查找:

  • 如果其中一個實例就是當(dāng)前-就是說,如果我們在繪制實例詳細信息頁面'author-polls'- 'polls:index'解析到的索引頁面'author-polls'實例; 即以下兩個都將導(dǎo)致"/author-polls/"。在基于類的視圖的方法中:reverse('polls:index', current_app=self.request.resolver_match.namespace)并在模板中:{% url 'polls:index' %}
  • 如果沒有當(dāng)前實例(例如,如果我們正在網(wǎng)站上其他地方渲染頁面),'polls:index'則將解析為的最后一個注冊實例polls。由于沒有默認實例(的實例名稱空間'polls'),因此polls將使用該實例的最后一個實例。這是'publisher-polls'因為它在中被聲明為最后一個urlpatterns。
  • 'author-polls:index'將始終解析為實例的索引頁 'author-polls'('publisher-polls')。

如果還存在一個默認實例(即名為的實例)'polls',則唯一的更改就是沒有當(dāng)前實例(上面列表中的第二項)。在這種情況下,'polls:index' 它將解析為默認實例的索引頁,而不是最后一個在中聲明的實例urlpatterns。

URL命名空間和包含的URLconf 

可以通過兩種方式指定包含的URLconf的應(yīng)用程序名稱空間。

首先,您可以app_name在包含的URLconf模塊中設(shè)置與該urlpatterns屬性相同級別的屬性。您必須將實際模塊或?qū)υ撃K的字符串引用傳遞給include(),而不是其urlpatterns自身的列表。

民調(diào)/的urls.py 

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]

的urls.py 

from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
]

中定義的URL polls.urls將具有一個應(yīng)用程序名稱空間polls。

其次,您可以包括一個包含嵌入式名稱空間數(shù)據(jù)的對象。如果您include()列出path()re_path()實例,則該對象中包含的URL將被添加到全局名稱空間中。但是,您還可以include()包含一個包含以下內(nèi)容的2元組:

(<list of path()/re_path() instances>, <application namespace>)

例如:

from django.urls import include, path

from . import views

polls_patterns = ([
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
], 'polls')

urlpatterns = [
    path('polls/', include(polls_patterns)),
]

這會將提名的URL模式包括到給定的應(yīng)用程序名稱空間中。

可以使用的namespace參數(shù) 指定實例名稱空間include()。如果未指定實例名稱空間,它將默認為包含的URLconf的應(yīng)用程序名稱空間。這意味著它將也是該名稱空間的默認實例。

詳細參考: https://docs.djangoproject.com/en/3.0/topics/http/urls/


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號