path('', views.IndexView.as_view(), name='datang')中name='datang'的作用
去除模板中的硬編碼 URL¶
還記得嗎,我們在 polls/index.html
裡編寫投票連結時,連結是硬編碼的:
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
問題在於,硬編碼和強耦合的連結,對於一個包含很多應用的專案來說,修改起來是十分困難的。然而,因為你在 polls.urls
的 url()
函式中通過 name 引數為 URL 定義了名字,你可以使用 {% url %}
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
這個標籤的工作方式是在 polls.urls
模組的 URL 定義中尋具有指定名字的條目。你可以回憶一下,具有名字 'detail' 的 URL 是在如下語句中定義的:
... # the 'name' value as called by the {% url %} template tag path('<int:question_id>/', views.detail, name='detail'), ...
如果你想改變投票詳情檢視的 URL,比如想改成 polls/specifics/12/
,你不用在模板裡修改任何東西(包括其它模板),只要在 polls/urls.py
裡稍微修改一下就行:
...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...
為 URL 名稱新增名稱空間¶
教程專案只有一個應用,polls
。在一個真實的 Django 專案中,可能會有五個,十個,二十個,甚至更多應用。Django 如何分辨重名的 URL 呢?舉個例子,polls
detail
檢視,可能另一個部落格應用也有同名的檢視。Django 如何知道 {% url %}
標籤到底對應哪一個應用的 URL 呢?
答案是:在根 URLconf 中新增名稱空間。在 polls/urls.py
檔案中稍作修改,加上 app_name
設定名稱空間:
polls/urls.py¶
from django.urls import path from . import views app_name = 'polls' urlpatterns = [ path('', views.index, name='index'), path('<int:question_id>/', views.detail, name='detail'), path('<int:question_id>/results/', views.results, name='results'), path('<int:question_id>/vote/', views.vote, name='vote'), ]
現在,編輯 polls/index.html
檔案,從:
polls/templates/polls/index.html¶
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
修改為指向具有名稱空間的詳細檢視:
polls/templates/polls/index.html¶
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
Reversing namespaced 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:
-
First, Django looks for a matching application namespace (in this example,
'polls'
). This will yield a list of instances of that application. -
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 thereverse()
function.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 therequest.current_app
attribute. -
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'
). -
If there is no default application instance, Django will pick the last deployed instance of the application, whatever its instance name may be.
-
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.
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.
例如¶
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.
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')),
]
polls/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'),
...
]
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:
reverse('polls:index', current_app=self.request.resolver_match.namespace)
and in the template:
{% url 'polls:index' %}
-
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 ofpolls
. Since there is no default instance (instance namespace of'polls'
), the last instance ofpolls
that is registered will be used. This would be'publisher-polls'
since it's declared last in theurlpatterns
. -
'author-polls:index'
will always resolve to the index page of the instance'author-polls'
(and likewise for'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
.