1. 程式人生 > >path('', views.IndexView.as_view(), name='datang')中name='datang'的作用

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:

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

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

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

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

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

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

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