Django 1.11中文文檔:URL dispatcher

已經同步到gitbook,想閱讀的請轉到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.

簡潔、優雅的URL設計對于高質量的web應用來說是非常重要的,Django允許你隨心所欲的設計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的發明者寫的Cool URIs don’t change,里面詳細說了為什么URLs應該簡潔易用。

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

要給應用設計URLs,需首先創建一個叫URLconf(URL 配置)的Python模塊。這個模塊是純粹的Python代碼,包含了URL模式(簡單正則表達式)到Python函數(你的視圖)的簡單映射。

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.

這個映射關系可長可短。也可以引用其他的映射。而且,由于它是純粹的Python代碼,它可以動態的調整。

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

Django還提供當前語言翻譯URL的一種方法,詳細信息參考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:

當一個用戶請求Django 站點的一個頁面,下面是Django 系統決定執行哪個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配置,但如果這個請求帶有urlconf 屬性(通過中間件設置),那它的值會覆蓋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加載該Python模塊并匹配url模式。它是django.conf.urls.url() 實例的Python列表。

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

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

  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:

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

  • An instance of HttpRequest.

  • 一個HttpRequest實例

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

  • 如果匹配的正則表達式返回的是未命名的組,那么正則表達式匹配的內容將作為位置參數提供給視圖

  • 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().

  • 關鍵字參數由正則表達式匹配的命名組組成,但是可被django.conf.urls.url()的可選參數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.

  • 如果沒有匹配到正則表達式,或者如果過程中拋出一個異常,Django 將調用一個錯誤處理視圖。請參見下面的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捕獲一個值,只需要加一個圓括號括起來即可

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

  • 開頭不需要再加斜杠,因為每個URL都有。比如說,應寫^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.

  • 每個正則表達式前面的‘r’不強求,但是推薦加上。它告訴python這個字符串是“原始的”——字符串中任何字符都不用轉義。參見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列表中的第三個。Django會調用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 模式,因為列表中的第三個模式要求月份應該是兩個數字。

  • /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/ 將匹配列表中的第一個模式不是第二個,因為模式按順序匹配,第一個會首先被匹配通過。為了應對這種情況,你可以在之前插入一些url特例,比如對這里而言,Django會調用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不會匹配任何模式,因為每個URL模式都要求以斜杠結尾

  • /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/將匹配最后一個,Django會調用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.

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

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 正則表達式中,命名正則表達式組的語法是(?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:

這基本與上次的例子是一樣的,只有一個細微差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數。例如:

  • 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/請求將調用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/ 請求將調用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.

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

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 解析器使用的算法,針對正則表達式中的命名組和非命名組:

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

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

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

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里的參數都會傳遞給view函數

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當做Python的字符串來處理。所以這不包括GET或POST的參數,以及域名。

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 不檢查使用了哪種請求方法。換句話講,所有的請求方法 —— 即,對同一個URL的無論是POST請求、GET請求、或HEAD請求方法等等 —— 都將路由到相同的函數。

Captured arguments are always strings?

捕獲的參數值均為字符串?

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:

每個捕獲的參數都作為一個普通的Python 字符串傳遞給視圖,無論正則表達式使用的是什么匹配方式。例如,下面這行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 參數將是一個字符串,即使[0-9]{4} 值匹配整數字符串。

Specifying defaults for view arguments?

指定視圖參數的默認值?

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

有一個方便的小技巧是指定視圖參數的默認值。 下面是一個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.

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

Performance?

性能?

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

urlpatterns 中的每個正則表達式在第一次訪問它們時被編譯。這使得系統相當快。

**Syntax of the urlpatterns

variable?**

urlpatterns變量的語法?

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

urlpatterns 應該是一個url() 實例類型的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.

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

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.

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

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

詳細文檔參見 customizing error views

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

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

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.

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

Including other URLconfs?

引入其他 URLconfs?

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

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

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

例如,下面是 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 ...
]

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.

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

Another possibility is to include additional URL patterns by using a list of url() instances. For example, consider this 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/$', 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.

在這個例子中,/credit/reports/ 將調用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:

這個可以用來去除冗余的URL前綴。比如下面這個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:

我們可以改進這種情況,使路徑的前綴只用一次,然后將后面不同的部分分組:

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?

捕獲的參數?

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

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

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

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

Nested arguments?

參數嵌套?

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:

正則表達式允許嵌套參數,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
]

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 (?:...).

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

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 視圖需要最外層捕獲的參數來反查,在這個例子中是page-2/或者沒有參數,而comments可以不帶參數或者用一個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.

嵌套捕獲的參數使得視圖參數和URL 之間存在強耦合,正如blog_articles 所示:視圖接收URL(page-2/)的一部分,而不只是視圖所要的值。這種耦合在反查時更加顯著,因為反查視圖時我們需要傳遞URL 的一個片段而不只是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.

作為一個經驗的法則,當正則表達式需要一個參數但視圖忽略它的時候,只捕獲視圖需要的值并使用非捕獲參數。

Passing extra options to view functions?

傳遞其他參數給view函數?

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

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

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() 函數可以接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。

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').

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

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

這個技術在 syndication framework中使用,來傳遞元數據和選項給視圖。

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 模式捕獲的命名關鍵字參數和在字典中傳遞的額外參數有可能具有相同的名稱。當這種情況發生時,將使用字典中的參數而不是URL 中捕獲的參數。

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

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

For example, these two URLconf sets are functionally identical:

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

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.

注意,額外的選項將永遠傳遞給被包含的URLconf 中的每一行,無論該行的視圖實際上是否認為這些選項是合法的。由于這個原因,該技術只有當你確定被包含的URLconf 中的每個視圖都接收你傳遞給它們的額外的選項時才有價值。

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

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

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.

人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 毫不相關的專門的URL 生成機制,因為這樣容易導致一定程度上產生過期的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.

換句話講,需要的是一個DRY 機制。除了其它優點,它還允許設計的URL 可以自動更新而不用遍歷項目的源代碼來搜索并替換過期的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里獲取到的最主要部分信息是找到處理它的視圖函數。以及還有其他一些必要信息,如視圖的參數類型(位置參數,關鍵字參數)和值。

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 設計唯一的儲存庫。你用你的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.

  • 用戶/瀏覽器發起URL 請求,它調用正確的Django 視圖,并從URL 中提取它的參數需要的值。

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

  • 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的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.

第一種方式是我們在前面的章節中一直討論的用法。第二種方式叫做反向解析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 標簽

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

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

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

  • 在更高層的與處理Django 模型實例相關的代碼中:使用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.

如果出于某種原因決定按年歸檔文章發布的URL應該調整一下,那么你將只需要修改URLconf 中的內容。

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.

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

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.

當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱沖突。如果你的URL 模式叫做comment,而另外一個應用中也有一個同樣的名稱, reverse() 返回的是項目urlpatterns 列表里最后一個同名的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 名稱中加上一個前綴,比如應用的名稱,將減少沖突的可能。我們建議使用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).

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

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

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 ,即使不同的應用使用相同的URL 名稱。第三方應用始終使用帶命名空間的URL 是一個很好的實踐(我們在教程中也是這么做的)。類似地,它還允許你在一個應用有多個實例部署的情況下反查URL。換句話講,因為一個應用的多個實例共享相同的命名URL,命名空間提供了一種區分這些命名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).

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

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

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

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

它表示正在部署的應用的名稱。一個應用的每個實例具有相同的應用命名空間。例如,容易知道Django 的管理站點應用命名空間是'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'.

它表示應用的一個特定的實例。實例的命名空間在你的全部項目中應該是唯一的。但是,一個實例的命名空間可以和應用的命名空間相同。它可用于表示一個應用的默認實例。例如,Django 管理站點實例的默認的實例命名空間是'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 的命名空間使用':' 分隔符分開。例如,管理站點應用的主頁使用'admin:index'。它表示'admin' 的一個命名空間和'index' 的一個命名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'.

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

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:

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

  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 在這個例子中為'polls'。這將得到該應用實例的一個列表。

  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.

如果當前應用屬性被定義,Django將查找并返回那個實例的URL解析器。當前應用屬性可在reverse() 函數中通過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 模板標簽在RequestContext將當前解析的視圖當作當前應用。你可以通過設置request.current_app
屬性重寫這個默認行為

  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').

如果沒有當前應用。Django 將查找一個默認的應用實例。
默認的應用實例是instance namespaceapplication namespace 一致的那個實例(在這個例子中,polls
的一個叫做'polls' 的實例)。

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

如果沒有默認的應用實例,Django 將挑選該應用最后部署的實例,不管實例的名稱是什么。

  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 將嘗試直接將此命名空間作為一個 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.

如果有嵌套的命名空間,將為命名空間的每個部分重復調用這些步驟直至剩下視圖的名稱還未解析。然后該視圖的名稱將被解析到找到的這個命名空間中的一個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.

為了演示解析的策略,如教程中兩個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')),
    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:

根據以上設置,可按如下查詢:

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

  • 如果其中一個實例是當前實例 —— 如果我們正在渲染'author-polls' 實例的detail 頁面 —— 'polls:index' 將解析成'author-polls' 實例的主頁面;例如下面兩個都將解析成"/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.

  • 如果沒有當前實例——假如說我們在站點的其他地方渲染頁面——'polls:index'將解析到最后注冊到polls的實例。因為沒有默認的實例(實例命名空間為polls),將用注冊的polls的最后一個實例。它將是'publisher-polls',因為它是urlpatterns中最后一個聲明的

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

  • 'author-polls:index' 將永遠解析到 'author-polls' 實例的主頁('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.

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

URL namespaces and included URLconfs?

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

included URLconfs的應用命名空間可通過兩種方式指定。

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的模塊中設置app_name屬性,與urlpatterns 變量同級。你需傳遞一個實際的模塊,或者一個關聯到那模塊的字符串,而不是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將有一個應用命名空間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:

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

(<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模式進入到給定的應用和實例命名空間中。

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()函數,實例命名空間可以用namespace參數指定。如果沒有指定instance namespace,它將默認include 與URLconf的應用命名空間。這意味著,它也是默認的實例命名空間。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容