URL 命名空间允许你使用唯一的反向命名URL模式( named URL patterns ),即便不同应用程序使用相同的 URL 名称。对于第三方应用程序来说,始终使用 URL 命名空间是个好习惯(像在教程里说的那样)。同样,如果已部署了应用程序的多个实例,它也允许你反向解析 URL。换句话说,因为单个应用的多个实例会分享已命名的 URL,命名空间提供了区分这些已命名 URL 的方法。
对于特定站点,正确使用URL名称空间的Django应用程序可以部署多次。比如 django.contrib.admin 有一个 AdminSite ,它允许admin实例部署多次。
URL 命名空间分为两部分,它们都是字符串:
这描述了正在部署的程序名。单个应用的每个实例拥有相同的命名空间。比如,Django admin 应用有可预测的应用命名空间 'admin' 。
这标识了应用程序的特定实例。实例命名空间应该是完整项目唯一的。但是实例命名空间可以和应用命名空间相同。这常用来指定应用的默认实例。比如,默认Django admin 实例拥有名为'admin' 的实例命名空间。
被指定的命名空间 URL 使用 ':' 操作符。比如,使用 'admin:index' 引用admin 应用的首页。这表明命名空间为 'admin' ,命名 URL 为 'index' 。
命名空间也可以嵌套。命名 URL 'sports:polls:index' 将在命名空间 'polls' 中寻找命名为 'index' 的模式,该模式是在顶层命名空间 'sports' 中定义的。
当给定一个命名空间 URL(例如 'polls:index' )解析时,Django 会将完全限定的名称拆分成多个部分,然后尝试下面的查询:
application namespace (这个例子里是 'polls' )。这将产生应用实例列表。 reverse() 函数的 current_app参数来指定当前应用程序。url 模板标签使用当前已解析的视图命名空间当作 RequestContext中的应用程序。你可以通过设置在 request.current_app 属性上的当前应用来覆盖这个默认配置。polls 实例被称为 'polls' )。 如果有嵌套的命名空间,则会对命名空间的每个部分重复这些步骤,直到视图名不被解析为止,然后视图名称将被解析为已找到的命名空间中的一个 URL 。
例如:
为了展示这个解决策略的实际作用,请考虑教程里 polls应用程序的两个实例案例:分别被称为 'author-polls' 和 'publisher-polls' 。假设我们已经增强了这个应用程序,以便会在创建和显示 polls时考虑实例命名空间
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')),
]
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'),
...
]
使用这步后,可以进行以下查找:
如果我们在实例 'author-polls' 中渲染详情页 - 'polls:index' 将解析为 'author-polls' 的首页;比如下面两种都将触发 "/author-polls/" 。
在基于类的视图里的方法:
reverse('polls:index', current_app=self.request.resolver_match.namespace) 在模板中:
{% url 'polls:index' %} 如果我们在站点某处渲染一个页面 - 'polls:index' 将被解析为 polls的最后一个注册实例。因为这里没有默认实例( 'polls' 的实例命名空间),所以将使用 polls的最后一个注册实例。这将是 'publisher-polls' ,因为它是在 urlpatterns 的最后面声明的。
'author-polls:index' 会一直被解析为实例 'author-polls' 的首页(对于 'publisher-polls' 同样如此)。
如果还有一个默认实例 - 例如,一个叫 'polls' 的实例 - 唯一的变化就是没有当前实例(上面列表中的第二项)。在这个例子 'polls:index' 将解析为默认实例的首页而不是在 urlpatterns中最后声明的实例。
有两种办法指定包含的URLconfs应用程序空间。
首先,你可以在包含的 URLcon 模块中设置一个 app_name 属性,在相同层作为 urlpatterns属性。你必须传递实际的模块或对该模块的一个字符串引用传递给 include() ,而不是 urlpatterns 本身的列表。
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'),
...
]
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
]
polls.urls 里的 URLs 定义将具有应用程序命名空间 polls。
其次,你可以包括一个包含嵌入式命名空间数据的对象。如果你 include() 了一个 path() 或 re_path() 实例的列表,那个对象里包含的 URLs 将被添加到全局命名空间内。但是,你也可以 include() 一个包含以下内容的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 模式包含到给定的应用程序命名空间里。
使用 include() 的 namespace 参数来指定实例命名空间。如果实例命名空间没有被指定,会默认已被导入的 URLconf 的应用程序命名空间。这意味着它也将成为那个命名空间的默认实例。