Django 1.11中文文檔:URL dispatcher

已經(jīng)同步到gitbook,想閱讀的請轉(zhuǎn)到gitbook: Django 1.10 中文文檔

URL dispatcher?

A clean, elegant URL scheme is an important detail in a high-quality Web application. Django lets you design URLs however you want, with no framework limitations.

簡潔、優(yōu)雅的URL設(shè)計(jì)對于高質(zhì)量的web應(yīng)用來說是非常重要的,Django允許你隨心所欲的設(shè)計(jì)URLs,而不受框架的約束。

There’s no .php or .cgi required, and certainly none of that 0,2097,1-1-1928,00 nonsense.

不再要求.php 或 .cgi ,更不會要求0,2097,1-1-1928,00這樣無意義 的東西

See Cool URIs don’t change, by World Wide Web creator Tim Berners-Lee, for excellent arguments on why URLs should be clean and usable.

參見World Wide Web的發(fā)明者寫的Cool URIs don’t change,里面詳細(xì)說了為什么URLs應(yīng)該簡潔易用。

Overview?

概覽?

To design URLs for an app, you create a Python module informally called a URLconf (URL configuration). This module is pure Python code and is a simple mapping between URL patterns (simple regular expressions) to Python functions (your views).

要給應(yīng)用設(shè)計(jì)URLs,需首先創(chuàng)建一個(gè)叫URLconf(URL 配置)的Python模塊。這個(gè)模塊是純粹的Python代碼,包含了URL模式(簡單正則表達(dá)式)到Python函數(shù)(你的視圖)的簡單映射。

This mapping can be as short or as long as needed. It can reference other mappings. And, because it’s pure Python code, it can be constructed dynamically.

這個(gè)映射關(guān)系可長可短。也可以引用其他的映射。而且,由于它是純粹的Python代碼,它可以動態(tài)的調(diào)整。

Django also provides a way to translate URLs according to the active language. See the internationalization documentation for more information.

Django還提供當(dāng)前語言翻譯URL的一種方法,詳細(xì)信息參考internationalization documentation

How Django processes a request?

How Django processes a request?

When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute:

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

  1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONFsetting, but if the incoming HttpRequest
    object has a urlconf attribute (set by middleware), its value will be used in place of the ROOT_URLCONF setting.

Django首先會使用root URLconf模塊。通常,這是 ROOT_URLCONF配置,但如果這個(gè)請求帶有urlconf 屬性(通過中間件設(shè)置),那它的值會覆蓋ROOT_URLCONF的配置

  1. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list of django.conf.urls.url() instances.

Django加載該P(yáng)ython模塊并匹配url模式。它是django.conf.urls.url() 實(shí)例的Python列表。

  1. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.

Django 依次匹配每個(gè)URL模式,直到匹配到第一個(gè)為止。

  1. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments:

一旦其中的一個(gè)正則表達(dá)式匹配上,Django 將導(dǎo)入并調(diào)用給出的視圖,它是一個(gè)簡單的Python 函數(shù)( 或者是class-based view)。視圖函數(shù)將獲得如下參數(shù):

  • An instance of HttpRequest.

  • 一個(gè)HttpRequest實(shí)例

  • If the matched regular expression returned no named groups, then the matches from the regular expression are provided as positional arguments.

  • 如果匹配的正則表達(dá)式返回的是未命名的組,那么正則表達(dá)式匹配的內(nèi)容將作為位置參數(shù)提供給視圖

  • The keyword arguments are made up of any named groups matched by the regular expression, overridden by any arguments specified in the optional kwargs argument to django.conf.urls.url().

  • 關(guān)鍵字參數(shù)由正則表達(dá)式匹配的命名組組成,但是可被django.conf.urls.url()的可選參數(shù)kwargs覆蓋。

  • If no regex matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

  • 如果沒有匹配到正則表達(dá)式,或者如果過程中拋出一個(gè)異常,Django 將調(diào)用一個(gè)錯誤處理視圖。請參見下面的Error handling

Example?

示例?

Here’s a sample 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),
]

Notes:

  • To capture a value from the URL, just put parenthesis around it.

  • 若要從URL捕獲一個(gè)值,只需要加一個(gè)圓括號括起來即可

  • There’s no need to add a leading slash, because every URL has that. For example, it’s ^articles, not ^/articles.

  • 開頭不需要再加斜杠,因?yàn)槊總€(gè)URL都有。比如說,應(yīng)寫^articles, 而不是 ^/articles.

  • The 'r' in front of each regular expression string is optional but recommended. It tells Python that a string is “raw” – that nothing in the string should be escaped. See Dive Into Python’s explanation.

  • 每個(gè)正則表達(dá)式前面的‘r’不強(qiáng)求,但是推薦加上。它告訴python這個(gè)字符串是“原始的”——字符串中任何字符都不用轉(zhuǎn)義。參見Dive Into Python’s explanation

Example requests:

請求的例子:

  • A request to /articles/2005/03/ would match the third entry in the list. Django would call the function views.month_archive(request, '2005', '03').

  • /articles/2005/03/ 請求會匹配到url列表中的第三個(gè)。Django會調(diào)用views.month_archive(request, '2005', '03').

  • /articles/2005/3/ would not match any URL patterns, because the third entry in the list requires two digits for the month.

  • /articles/2005/3/ 不匹配任何URL 模式,因?yàn)榱斜碇械牡谌齻€(gè)模式要求月份應(yīng)該是兩個(gè)數(shù)字。

  • /articles/2003/ would match the first pattern in the list, not the second one, because the patterns are tested in order, and the first one is the first test to pass. Feel free to exploit the ordering to insert special cases like this. Here, Django would call the function views.special_case_2003(request)

  • /articles/2003/ 將匹配列表中的第一個(gè)模式不是第二個(gè),因?yàn)槟J桨错樞蚱ヅ?,第一個(gè)會首先被匹配通過。為了應(yīng)對這種情況,你可以在之前插入一些url特例,比如對這里而言,Django會調(diào)用views.special_case_2003(request)。

  • /articles/2003 would not match any of these patterns, because each pattern requires that the URL end with a slash.

  • /articles/2003不會匹配任何模式,因?yàn)槊總€(gè)URL模式都要求以斜杠結(jié)尾

  • /articles/2003/03/03/ would match the final pattern. Django would call the function views.article_detail(request, '2003', '03', '03').

  • /articles/2003/03/03/將匹配最后一個(gè),Django會調(diào)用views.article_detail(request, '2003', '03', '03')

Named groups?

命名組?

The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

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

In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name
is the name of the group and pattern is some pattern to match.

在Python 正則表達(dá)式中,命名正則表達(dá)式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式。

Here’s the above example URLconf, rewritten to use named groups:

在上面示例中的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),
]

This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments. For example:

這基本與上次的例子是一樣的,只有一個(gè)細(xì)微差別:捕獲的值作為關(guān)鍵字參數(shù)而不是位置參數(shù)傳遞給視圖函數(shù)。例如:

  • A request to /articles/2005/03/ would call the function views.month_archive(request, year='2005', month='03'), instead of views.month_archive(request, '2005', '03').

  • /articles/2005/03/請求將調(diào)用views.month_archive(request, year='2005', month='03'),而不是views.month_archive(request, '2005', '03')

  • A request to /articles/2003/03/03/ would call the function views.article_detail(request, year='2003', month='03', day='03').

  • /articles/2003/03/03/ 請求將調(diào)用views.article_detail(request, year='2003', month='03', day='03').

In practice, this means your URLconfs are slightly more explicit and less prone to argument-order bugs – and you can reorder the arguments in your views’ function definitions. Of course, these benefits come at the cost of brevity; some developers find the named-group syntax ugly and too verbose.

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

The matching/grouping algorithm?

匹配/分組的算法?

Here’s the algorithm the URLconf parser follows, with respect to named groups vs. non-named groups in a regular expression:

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

  1. If there are any named arguments, it will use those, ignoring non-named arguments.

如果有命名參數(shù),則使用這些命名參數(shù),忽略非命名參數(shù)。

  1. Otherwise, it will pass all non-named arguments as positional arguments.
    否則,它將以位置參數(shù)傳遞所有的非命名參數(shù)。

In both cases, any extra keyword arguments that have been given as per Passing extra options to view functions(below) will also be passed to the view.

以上兩種情況, Passing extra options to view functions里的參數(shù)都會傳遞給view函數(shù)

What the URLconf searches against?

What the URLconf searches against?

URLconf如何搜索?

The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.

URLconf將請求的URL當(dāng)做Python的字符串來處理。所以這不包括GET或POST的參數(shù),以及域名。

For example, in a request to https://www.example.com/myapp/, the URLconf will look for myapp/.

比如說,https://www.example.com/myapp/請求中,URLconf會查找myapp/

In a request to https://www.example.com/myapp/?page=3, the URLconf will look for myapp/.

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

The URLconf doesn’t look at the request method. In other words, all request methods – POST, GET, HEAD, etc. – will be routed to the same function for the same URL.

URLconf 不檢查使用了哪種請求方法。換句話講,所有的請求方法 —— 即,對同一個(gè)URL的無論是POST請求、GET請求、或HEAD請求方法等等 —— 都將路由到相同的函數(shù)。

Captured arguments are always strings?

捕獲的參數(shù)值均為字符串?

Each captured argument is sent to the view as a plain Python string, regardless of what sort of match the regular expression makes. For example, in this URLconf line:

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

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

...the year
argument passed to views.year_archive()
will be a string,not an integer, even though the [0-9]{4} will only match integer strings.

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

Specifying defaults for view arguments?

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

A convenient trick is to specify default parameters for your views’ arguments. Here’s an example URLconf and view:

有一個(gè)方便的小技巧是指定視圖參數(shù)的默認(rèn)值。 下面是一個(gè)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.
    ...

In the above example, both URL patterns point to the same view – views.page – but the first pattern doesn’t capture anything from the URL. If the first pattern matches, the page() function will use its default argument for num, "1". If the second pattern matches, page() will use whatever num value was captured by the regex.

在上面的例子中,兩個(gè)URL模式指向同一個(gè)視圖views.page —— 但是第一個(gè)模式不會從URL 中捕獲任何值。如果第一個(gè)模式匹配,page() 函數(shù)將使用num參數(shù)的默認(rèn)值"1"。如果第二個(gè)模式匹配,page() 將使用正則表達(dá)式捕獲的num 值。

Performance?

性能?

Each regular expression in a urlpatterns is compiled the first time it’s accessed. This makes the system blazingly fast.

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

**Syntax of the urlpatterns

variable?**

urlpatterns變量的語法?

urlpatterns should be a Python list of url() instances.

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

Error handling?

錯誤處理?

When Django can’t find a regex matching the requested URL, or when an exception is raised, Django will invoke an error-handling view.

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

The views to use for these cases are specified by four variables. Their default values should suffice for most projects, but further customization is possible by overriding their default values.

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

See the documentation on customizing error views for the full details.

詳細(xì)文檔參見 customizing error views

Such values can be set in your root URLconf. Setting these variables in any other URLconf will have no effect.

這些值可以在你的根URLconf 中設(shè)置。在其它URLconf 中設(shè)置這些變量將不起作用。

Values must be callables, or strings representing the full Python import path to the view that should be called to handle the error condition at hand.

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

Including other URLconfs?

引入其他 URLconfs?

At any point, your urlpatterns can “include” other URLconf modules. This essentially “roots” a set of URLs below other ones.

在任何時(shí)候,你的urlpatterns 都可以包含其它URLconf 模塊。本質(zhì)上說“roots”是其他URLs的一個(gè)集合。

For example, here’s an excerpt of the URLconf for the Django website itself. It includes a number of other URLconfs:

例如,下面是 Django 網(wǎng)站自己的URLconf 中一個(gè)片段。它包含許多其它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 ...
]

Note that the regular expressions in this example don’t have a $
(end-of-string match character) but do include a trailing slash. Whenever Django encounters include()
(django.conf.urls.include()), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

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

Another possibility is to include additional URL patterns by using a list of url() instances. For example, consider this URLconf:

另外一種包含其它URL 模式的方式是使用一個(gè)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/$', credit_views.report),
    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)),
]

In this example, the /credit/reports/ URL will be handled by the credit_views.report() Django view.

在這個(gè)例子中,/credit/reports/ 將調(diào)用credit_views.report()視圖

This can be used to remove redundancy from URLconfs where a single pattern prefix is used repeatedly. For example, consider this URLconf:

這個(gè)可以用來去除冗余的URL前綴。比如下面這個(gè)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),
]

We can improve this by stating the common path prefix only once and grouping the suffixes that differ:

我們可以改進(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),
    ])),
]

Captured parameters?

捕獲的參數(shù)?

An included URLconf receives any captured parameters from parent URLconfs, so the following example is valid:

被包含的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),
]

In the above example, the captured "username" variable is passed to the included URLconf, as expected.

在上面的例子中,捕獲的"username"變量將被傳遞給include()指向的URLconf。

Nested arguments?

參數(shù)嵌套?

Regular expressions allow nested arguments, and Django will resolve them and pass them to the view. When reversing, Django will try to fill in all outer captured arguments, ignoring any nested captured arguments. Consider the following URL patterns which optionally take a page argument:

正則表達(dá)式允許嵌套參數(shù),Django 將解析它們并傳遞給視圖。當(dāng)反查時(shí),Django 將嘗試填滿所有外圍捕獲的參數(shù),并忽略嵌套捕獲的參數(shù)。考慮下面的URL 模式,它帶有一個(gè)可選的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
]

Both patterns use nested arguments and will resolve: for example, blog/page-2/ will result in a match to blog_articles with two positional arguments: page-2/ and 2. The second pattern for comments will match comments/page-2/ with keyword argument page_number set to 2. The outer argument in this case is a non-capturing argument (?:...).

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

The blog_articles view needs the outermost captured argument to be reversed, page-2/ or no arguments in this case, while comments can be reversed with either no arguments or a value for page_number.

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

Nested captured arguments create a strong coupling between the view arguments and the URL as illustrated by blog_articles: the view receives part of the URL (page-2/) instead of only the value the view is interested in. This coupling is even more pronounced when reversing, since to reverse the view we need to pass the piece of URL instead of the page number.

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

As a rule of thumb, only capture the values the view needs to work with and use non-capturing arguments when the regular expression needs an argument but the view ignores it.

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

Passing extra options to view functions?

傳遞其他參數(shù)給view函數(shù)?

URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.

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

The django.conf.urls.url() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

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

For example:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

In this example, for a request to /blog/2005/, Django will all views.year_archive(request,year='2005', foo='bar').

在這個(gè)例子中,對于/blog/2005/
請求,Django 將調(diào)用views.year_archive(request, year='2005', foo='bar')。

This technique is used in the syndication framework to pass metadata and options to views.

這個(gè)技術(shù)在 syndication framework中使用,來傳遞元數(shù)據(jù)和選項(xiàng)給視圖。

Dealing with conflicts

It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.

處理沖突

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

**Passing extra options to include()

?**

Similarly, you can pass extra options to include(). When you pass extra options to include(), each line in the included URLconf will be passed the extra options.

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

For example, these two URLconf sets are functionally identical:

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

Set one:

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

Set two:

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

Note that extra options will always be passed to every line in the included URLconf, regardless of whether the line’s view actually accepts those options as valid. For this reason, this technique is only useful if you’re certain that every view in the included URLconf accepts the extra options you’re passing.

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

Reverse resolution of URLs?

URLs反向解析?

A common need when working on a Django project is the possibility to obtain URLs in their final forms either for embedding in generated content (views and assets URLs, URLs shown to the user, etc.) or for handling of the navigation flow on the server side (redirections, etc.)

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

It is strongly desirable to avoid hard-coding these URLs (a laborious, non-scalable and error-prone strategy). Equally dangerous is devising ad-hoc mechanisms to generate URLs that are parallel to the design described by the URLconf, which can result in the production of URLs that become stale over time.

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

In other words, what’s needed is a DRY mechanism. Among other advantages it would allow evolution of the URL design without having to go over all the project source code to search and replace outdated URLs.

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

The primary piece of information we have available to get a URL is an identification (e.g. the name) of the view in charge of handling it. Other pieces of information that necessarily must participate in the lookup of the right URL are the types (positional, keyword) and values of the view arguments.

我們能從URL里獲取到的最主要部分信息是找到處理它的視圖函數(shù)。以及還有其他一些必要信息,如視圖的參數(shù)類型(位置參數(shù),關(guān)鍵字參數(shù))和值。

Django provides a solution such that the URL mapper is the only repository of the URL design. You feed it with your URLconf and then it can be used in both directions:

Django 提供的解決方案是使得URL 映射是URL 設(shè)計(jì)唯一的儲存庫。你用你的URLconf填充它,然后可以雙向使用它:

  • Starting with a URL requested by the user/browser, it calls the right Django view providing any arguments it might need with their values as extracted from the URL.

  • 用戶/瀏覽器發(fā)起URL 請求,它調(diào)用正確的Django 視圖,并從URL 中提取它的參數(shù)需要的值。

  • Starting with the identification of the corresponding Django view plus the values of arguments that would be passed to it, obtain the associated URL.

  • 根據(jù)Django 視圖的標(biāo)識和將要傳遞給它的參數(shù)的值,獲取與之關(guān)聯(lián)的URL。

The first one is the usage we’ve been discussing in the previous sections. The second one is what is known as reverse resolution of URLs, reverse URL matching, reverse URL lookup, or simply URL reversing.

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

Django provides tools for performing URL reversing that match the different layers where URLs are needed:

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

  • In templates: Using the url template tag.

  • 在模板中:使用url 標(biāo)簽

  • In Python code: Using the reverse() function.

  • Python代碼里,用 reverse() 函數(shù)

  • In higher level code related to handling of URLs of Django model instances: The get_absolute_url()method.

  • 在更高層的與處理Django 模型實(shí)例相關(guān)的代碼中:使用get_absolute_url()
    方法。

Examples?

Consider again this URLconf entry:

from django.conf.urls import url

from . import views

urlpatterns = [
    #...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...
]

According to this design, the URL for the archive corresponding to year nnnn is /articles/nnnn/.

You can obtain these in template code by using:

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

Or in Python code:

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

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

If, for some reason, it was decided that the URLs where content for yearly article archives are published at should be changed then you would only need to change the entry in the URLconf.

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

In some scenarios where views are of a generic nature, a many-to-one relationship might exist between URLs and views. For these cases the view name isn’t a good enough identifier for it when comes the time of reversing URLs. Read the next section to know about the solution Django provides for this.

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

Naming URL patterns?

命名URL patterns?

In order to perform URL reversing, you’ll need to use named URL patterns as done in the examples above. The string used for the URL name can contain any characters you like. You are not restricted to valid Python names.

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

When naming URL patterns, choose names that are unlikely to clash with other applications’ choice of names. If you call your URL pattern comment and another application does the same thing, the URL that reverse() finds depends on whichever pattern is last in your project’s urlpatterns list.

當(dāng)命名你的URL 模式時(shí),請確保使用的名稱不會與其它應(yīng)用中名稱沖突。如果你的URL 模式叫做comment,而另外一個(gè)應(yīng)用中也有一個(gè)同樣的名稱, reverse() 返回的是項(xiàng)目urlpatterns 列表里最后一個(gè)同名的URL。

Putting a prefix on your URL names, perhaps derived from the application name (such as myapp-comment instead of comment), decreases the chance of collision.

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

You can deliberately choose the same URL name as another application if you want to override a view. For example, a common use case is to override the LoginView. Parts of Django and most third-party apps assume that this view has a URL pattern with the name login. If you have a custom login view and give its URL the name login,reverse() will find your custom view as long as it’s in urlpatterns after django.contrib.auth.urls is included (if that’s included at all).

你可以故意選擇與其他應(yīng)用同名的URL名字來重寫一個(gè)視圖函數(shù)。比如說,常用的是重寫登錄視圖LoginView。部分Django或大多數(shù)的第三方應(yīng)用都認(rèn)為這個(gè)登錄視圖的URL名稱為login。如果你有一個(gè)登錄視圖并命名為login,在將它的urlpatterns用django.contrib.auth.urls引入后,reverse() 函數(shù)返回的將是你自定義的view。

You may also use the same name for multiple URL patterns if they differ in their arguments. In addition to the URL name, reverse() matches the number of arguments and the names of the keyword arguments.

你同樣可以為多個(gè)URL模式起相同的名字,如果他們的參數(shù)不同的話。除了URL名字外, reverse()還會匹配參數(shù)的個(gè)數(shù)以及關(guān)鍵字參數(shù)。

URL namespaces?

Introduction?

URL namespaces allow you to uniquely reverse named URL patterns even if different applications use the same URL names. It’s a good practice for third-party apps to always use namespaced URLs (as we did in the tutorial). Similarly, it also allows you to reverse URLs if multiple instances of an application are deployed. In other words, since multiple instances of a single application will share named URLs, namespaces provide a way to tell these named URLs apart.

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

Django applications that make proper use of URL namespacing can be deployed more than once for a particular site. For example django.contrib.admin has an AdminSite class which allows you to easily deploy more than one instance of the admin. In a later example, we’ll discuss the idea of deploying the polls application from the tutorial in two different locations so we can serve the same functionality to two different audiences (authors and publishers).

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

A URL namespace comes in two parts, both of which are strings:

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

application namespace
This describes the name of the application that is being deployed. Every instance of a single application will have the same application namespace. For example, Django’s admin application has the somewhat predictable application namespace of 'admin'.

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

instance namespace
This identifies a specific instance of an application. Instance namespaces should be unique across your entire project. However, an instance namespace can be the same as the application namespace. This is used to specify a default instance of an application. For example, the default Django admin instance has an instance namespace of 'admin'.

它表示應(yīng)用的一個(gè)特定的實(shí)例。實(shí)例的命名空間在你的全部項(xiàng)目中應(yīng)該是唯一的。但是,一個(gè)實(shí)例的命名空間可以和應(yīng)用的命名空間相同。它可用于表示一個(gè)應(yīng)用的默認(rèn)實(shí)例。例如,Django 管理站點(diǎn)實(shí)例的默認(rèn)的實(shí)例命名空間是'admin'。

Namespaced URLs are specified using the ':' operator. For example, the main index page of the admin application is referenced using 'admin:index'. This indicates a namespace of 'admin', and a named URL of 'index'.

URL 的命名空間使用':' 分隔符分開。例如,管理站點(diǎn)應(yīng)用的主頁使用'admin:index'。它表示'admin' 的一個(gè)命名空間和'index' 的一個(gè)命名URL。

Namespaces can also be nested. The named URL 'sports:polls:index' would look for a pattern named 'index' in the namespace 'polls' that is itself defined within the top-level namespace 'sports'.

命名空間也可以嵌套。對于這個(gè)URL名稱'sports:polls:index' ,首先在頂層命名空間'sports' 中找到polls命名空間,再找到index實(shí)例命名空間。

Reversing namespaced URLs?

反向解析帶命名空間的URLs?

When given a namespaced URL (e.g. 'polls:index') to resolve, Django splits the fully qualified name into parts and then tries the following lookup:

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

  1. First, Django looks for a matching application namespace (in this example, 'polls'). This will yield a list of instances of that application.

首先,Django 查找匹配的 application namespace 在這個(gè)例子中為'polls'。這將得到該應(yīng)用實(shí)例的一個(gè)列表。

  1. If there is a current application defined, Django finds and returns the URL resolver for that instance. The current application can be specified with the current_app
    argument to the reverse() function.

如果當(dāng)前應(yīng)用屬性被定義,Django將查找并返回那個(gè)實(shí)例的URL解析器。當(dāng)前應(yīng)用屬性可在reverse() 函數(shù)中通過current_app來指定

The url template tag uses the namespace of the currently resolved view as the current application in aRequestContext. You can override this default by setting the current application on the request.current_app
attribute.

url 模板標(biāo)簽在RequestContext將當(dāng)前解析的視圖當(dāng)作當(dāng)前應(yīng)用。你可以通過設(shè)置request.current_app
屬性重寫這個(gè)默認(rèn)行為

  1. If there is no current application. Django looks for a default application instance. The default application instance is the instance that has an instance namespace matching the application namespace (in this example, an instance of polls called 'polls').

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

  1. If there is no default application instance, Django will pick the last deployed instance of the application, whatever its instance name may be.

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

  1. If the provided namespace doesn’t match an application namespace in step 1, Django will attempt a direct lookup of the namespace as an instance namespace.

如果提供的命名空間與第1步中的application namespace 不匹配,Django 將嘗試直接將此命名空間作為一個(gè) instance namespace查找。

If there are nested namespaces, these steps are repeated for each part of the namespace until only the view name is unresolved. The view name will then be resolved into a URL in the namespace that has been found.

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

Example?

To show this resolution strategy in action, consider an example of two instances of the polls application from the tutorial: one called 'author-polls' and one called 'publisher-polls'. Assume we have enhanced that application so that it takes the instance namespace into consideration when creating and displaying polls.

為了演示解析的策略,如教程中兩個(gè)polls應(yīng)用的實(shí)例:'author-polls' 和'publisher-polls'。假設(shè)我們已經(jīng)改進(jìn)了這個(gè)應(yīng)用,在創(chuàng)建和顯示投票時(shí)考慮了實(shí)例命名空間。
urls.py

from django.conf.urls import include, url

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

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
    ...
]

Using this setup, the following lookups are possible:

根據(jù)以上設(shè)置,可按如下查詢:

  • If one of the instances is current - say, if we were rendering the detail page in the instance 'author-polls' - 'polls:index' will resolve to the index page of the 'author-polls' instance; i.e. both of the following will result in "/author-polls/".

    In the method of a class-based view:

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

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

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

and in the template:

{% url 'polls:index' %}

注意,在模板中的反查需要添加request 的current_app 屬性,像這樣:

  • If there is no current instance - say, if we were rendering a page somewhere else on the site - 'polls:index' will resolve to the last registered instance of polls. Since there is no default instance (instance namespace of 'polls'), the last instance of polls that is registered will be used. This would be 'publisher-polls' since it’s declared last in the urlpatterns.

  • 如果沒有當(dāng)前實(shí)例——假如說我們在站點(diǎn)的其他地方渲染頁面——'polls:index'將解析到最后注冊到polls的實(shí)例。因?yàn)闆]有默認(rèn)的實(shí)例(實(shí)例命名空間為polls),將用注冊的polls的最后一個(gè)實(shí)例。它將是'publisher-polls',因?yàn)樗莡rlpatterns中最后一個(gè)聲明的

  • 'author-polls:index' will always resolve to the index page of the instance 'author-polls' (and likewise for 'publisher-polls') .

  • 'author-polls:index' 將永遠(yuǎn)解析到 'author-polls' 實(shí)例的主頁('publisher-polls' 類似)。

If there were also a default instance - i.e., an instance named 'polls' - the only change from above would be in the case where there is no current instance (the second item in the list above). In this case 'polls:index' would resolve to the index page of the default instance instead of the instance declared last in urlpatterns.

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

URL namespaces and included URLconfs?

Application namespaces of included URLconfs can be specified in two ways.

included URLconfs的應(yīng)用命名空間可通過兩種方式指定。

Firstly, you can set an app_name
attribute in the included URLconf module, at the same level as the urlpatterns attribute. You have to pass the actual module, or a string reference to the module, to include(), not the list of urlpatterns itself.

第一種方式,你可以在被include的模塊中設(shè)置app_name屬性,與urlpatterns 變量同級。你需傳遞一個(gè)實(shí)際的模塊,或者一個(gè)關(guān)聯(lián)到那模塊的字符串,而不是urlpatterns列表自己

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
    ...
]

urls.py

from django.conf.urls import include, url

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
]

The URLs defined in polls.urls will have an application namespace polls.

polls.urls中定義URLs將有一個(gè)應(yīng)用命名空間polls

Secondly, you can include an object that contains embedded namespace data. If you include() a list of url()instances, the URLs contained in that object will be added to the global namespace. However, you can also include()
a 2-tuple containing:

第二種方式,你可以引入一個(gè)對象,對象要包含一個(gè)內(nèi)嵌的命名空間數(shù)據(jù)。如果你 include()一個(gè)url()實(shí)例的列表,那么包含那個(gè)對象URLs將被添加到全局命名空間。然而,你也可以include()一個(gè)2個(gè)元素的元組:

(<list of url() instances>, <application namespace>)

For example:

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

urlpatterns = [
    url(r'^polls/', include(polls_patterns)),
]

This will include the nominated URL patterns into the given application namespace.

這樣會包含命名的URL模式進(jìn)入到給定的應(yīng)用和實(shí)例命名空間中。

The instance namespace can be specified using the namespace
argument to include(). If the instance namespace is not specified, it will default to the included URLconf’s application namespace. This means it will also be the default instance for that namespace.

對于include()函數(shù),實(shí)例命名空間可以用namespace參數(shù)指定。如果沒有指定instance namespace,它將默認(rèn)include 與URLconf的應(yīng)用命名空間。這意味著,它也是默認(rèn)的實(shí)例命名空間。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容