blog/docs/code/django/urls.md

838 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 路由Urls
date: 2020-10-30 17:13:36
tags: [Django, Urls]
categories: [Django]
author: Anges黎梦
---
## 什么是URL
> URLUniform Resource Locator统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL用于指出文件的路径位置。也就可以理解为URL就是常说的网址每一个地址代表了不同的网页在Django中URL也成为URLconf。
## 初始项目的urls
![](https://limeng-blog.oss-cn-hangzhou.aliyuncs.com/code/django/demo.png)
这是一个纯净项目的url配置文件他存在的目录是与setting文件在同一个目录中。
urlpatterns就是一个保存url配置的变量他的类型是list。
创建项目之后,这个文件中有一些例子了。
但是他在注释中也给了我们一些其他的用法。
第一种,就是他例子中的直接相对地址加上视图函数的名称。
第二种则是导入urls文件这样也给了我们其他更方便的配置方法不必把所有的内容写到一个文件下。
我们可以通过include的方式把在其他位置写好的url配置文件导入进去。
同时,路径的匹配,还支持正则表达式。
```
# 导入Admin功能模块
from django.contrib import admin
# 导入URL编写模块
from django.urls import path
# urlpatterns 整个项目的url集合每一个元素代表一条url信息
urlpatterns = [
# 设定admin的url
path('admin/', admin.site.urls),
]
```
'admin/' 代表的是127.0.0.1:8000/admin的地址后面的斜杠是路径分隔符。
admin.site.urls是url的处理函数即视图函数
## URLconfs中的方法
### path()
path**(***route***,** *view***,** *kwargs=None***,** *name=None***)**
返回包含在中的元素`urlpatterns`
```
from django.urls import include, path
urlpatterns = [
path('index/', views.index, name='main-view'),
path('bio/<username>/', views.bio, name='bio'),
path('articles/<slug:title>/', views.article, name='article-detail'),
path('articles/<slug:title>/<int:section>/', views.section, name='article-section'),
path('weblog/', include('blog.urls')),
...
]
```
**route**参数应该是一个字符串或 gettext_lazy()其中包含一个URL模式。该字符串可能包含尖括号`<username>`如上所示以捕获URL的一部分并将其作为关键字参数发送到视图。尖括号可以包括转换器规范如`int`部分`<int:section>`),其限制匹配的字符并且还可以改变传递给视图的变量的类型。例如,`<int:section>`匹配一串十进制数字并将值转换为a `int`
`view`参数是一个视图函数或的结果 as_view()为基于类的视图。它也可以是一个django.urls.include()。
该`kwargs`参数允许您将其他参数传递给视图函数或方法。
有关 name参数的内容见url命名空间。
### re_path()
`re_path`**(***route***,** *view***,** *kwargs=None***,** *name=None***)**
```
from django.urls import include, re_path
urlpatterns = [
re_path(r'^index/$', views.index, name='index'),
re_path(r'^bio/(?P<username>\w+)/$', views.bio, name='bio'),
re_path(r'^weblog/', include('blog.urls')),
...
]
```
该`route`参数应该是一个字符串或 gettext_lazy()其中包含与Python的兼容的正则表达式 re模块。字符串通常使用原始字符串语法`r''`),以便它们可以包含序列,`\d`而无需使用另一个反斜杠转义反斜杠。进行匹配时,将正则表达式中捕获的组传递给视图 - 如果组已命名,则作为命名参数,否则作为位置参数。值以字符串形式传递,不进行任何类型转换。
的`view``kwargs`和`name`参数是一样的 path()
### include()
`include`*module**namespace = None*
`include`*pattern_list*
`include`*pattern_list**app_namespace**namespace = None*
一个函数它将完整的Python导入路径带到另一个URLconf模块该模块应该“包含”在这个地方。可选地还可以指定将包括条目的应用程序命名空间和实例命名空间。
通常,应用程序命名空间应由包含的模块指定。如果设置了应用程序命名空间,则该`namespace`参数可用于设置不同的实例命名空间。
`include()` 也接受返回URL模式的iterable或包含此类iterable的2元组以及应用程序命名空间的名称作为参数。
More Actions参数
- **module** - URLconf模块或模块名称
- **namespace**[*str*](https://docs.python.org/3/library/stdtypes.html#str) - 包含的URL条目的实例名称空间
- **pattern_list** - Iterable [`path()`](https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.path)和/或[`re_path()`](https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.re_path)实例。
- **app_namespace**[*str*](https://docs.python.org/3/library/stdtypes.html#str) - 包含的URL条目的应用程序命名空间
### `register_converter()`
`register_converter`*converter**type_name*
注册转换器以在s中使用的功能。path route
该`converter`参数是一个转换器类,并且`type_name`是在路径模式来使用转换器的名称。
## URLconfs中使用的函数
### static()
- `static.``static`*前缀**视图= django.views.static.serve**** kwargs*)
Helper函数在调试模式下返回服务文件的URL模式
```
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
```
## URL调度程序
干净优雅的URL方案是高质量Web应用程序中的重要细节。Django允许您根据需要设计URL没有框架限制。
没有`.php`或没有`.cgi`必要,当然也没有 `0,2097,1-1-1928,00`废话。
### 概述
要设计应用程序的URL可以创建一个非正式的称为**URLconf**URL配置的Python模块 。此模块是纯Python代码是URL路径表达式与Python函数您的视图之间的映射。
该映射可以根据需要缩短或缩短。它可以引用其他映射。而且因为它是纯Python代码所以它可以动态构建。
Django还提供了一种根据活动语言翻译URL的方法详细的可以看官方文档。
### Django如何处理请求
当用户从Django支持的站点请求页面时这是系统遵循的算法以确定要执行的Python代码
1. Django确定要使用的根URLconf模块。通常这是`ROOT_URLCONF`设置的值,但如果传入 `HttpRequest`对象具有`urlconf`属性(由中间件设置),则将使用其值代替 `ROOT_URLCONF`设置。
2. Django加载Python模块并查找变量 `urlpatterns`。这应该是Python列表`django.urls.path()` 和/或`django.urls.re_path()`实例。
3. Django按顺序遍历每个URL模式并在匹配请求的URL的第一个模式停止。
4. 一旦其中一个URL模式匹配Django就会导入并调用给定的视图这是一个简单的Python函数或基于
类的视图
)。视图传递以下参数:
- 一个例子`HttpRequest`。
- 如果匹配的URL模式未返回任何命名组则正则表达式中的匹配将作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,由或者 可选`kwargs`参数中指定的任何参数覆盖 。`django.urls.path()``django.urls.re_path()`
5. 如果没有URL模式匹配或者在此过程中的任何点期间引发异常Django将调用适当的错误处理视图。请参阅下面的错误处理。
### 示例
这是一个示例URLconf
```
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
```
笔记:
- 要从URL捕获值请使用尖括号。
- 捕获的值可以选择包括转换器类型。例如,用于 `<int:name>`捕获整数参数。如果未包含转换器`/`,则匹配除字符之外的任何字符串。
- 没有必要添加前导斜杠因为每个URL都有。例如它`articles`不是`/articles`。
示例请求:
- 请求`/articles/2005/03/`与列表中的第三个条目匹配。Django会调用该函数 。`views.month_archive(request, year=2005,month=3)`
- `/articles/2003/`将匹配列表中的第一个模式而不是第二个模式因为模式是按顺序测试的第一个是第一个要通过的测试。随意利用订单插入这样的特殊情况。在这里Django会调用该函数 `views.special_case_2003(request)`
- `/articles/2003` 不匹配任何这些模式因为每个模式都要求URL以斜杠结尾。
- `/articles/2003/03/building-a-django-site/`将匹配最终模式。Django会调用该函数 。`views.article_detail(request,year=2003, month=3, slug="building-a-django-site")`
## 路径转换器
默认情况下,以下路径转换器可用:
- `str`- 匹配除路径分隔符之外的任何非空字符串`'/'`。如果转换器未包含在表达式中,则这是默认值。
- `int` - 匹配零或任何正整数。返回一个int。
- `slug` - 匹配由ASCII字母或数字组成的任何slug字符串以及连字符和下划线字符。例如 `building-your-1st-django-site`
- `uuid` - 匹配格式化的UUID。要防止多个URL映射到同一页面必须包含短划线并且字母必须为小写。例如`075194d3-6885-417e-a8a8-6c931e272f00`。返回一个 [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID)实例。
- `path`- 匹配任何非空字符串,包括路径分隔符 `'/'`。这允许您匹配完整的URL路径而不仅仅是URL路径的一部分`str`。
## 注册自定义路径转换器
对于更复杂的匹配要求,您可以定义自己的路径转换器。
转换器是一个包含以下内容的类:
- 一个`regex`class属性作为字符串。
- 甲方法,它处理匹配的字符串转换成要传递到视图函数的类型。如果它不能转换给定值,它应该提高。`to_python(self,value)``ValueError`
- 一种方法用于处理将Python类型转换为要在URL中使用的字符串。`to_url(self, value)`
例如:
```
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
```
使用`register_converter()`以下命令在URLconf中注册自定义转换器类
```
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
```
## 使用正则表达式
如果路径和转换器语法不足以定义URL模式则还可以使用正则表达式。为此请使用 `re_path()`而不是`path()`。
在Python正则表达式中命名正则表达式组的语法是`(?P<name>pattern)`,组`name`的名称,并且 `pattern`是要匹配的模式。
这是前面的示例URLconf使用正则表达式重写
```
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]
```
这完成了与前一个示例大致相同的事情,除了:
- 匹配的确切网址稍微受限制。例如年份10000将不再匹配因为年份整数被限制为恰好四位数。
- 无论正则表达式的匹配类型如何,每个捕获的参数都将作为字符串发送到视图。
从使用切换`path()`到 `re_path()`反之亦然,特别重要的是要注意视图参数的类型可能会发生变化,因此您可能需要调整视图。
## 使用未命名的正则表达式组
除了命名组语法之外,例如`(?P<year>[0-9]{4})`,您还可以使用较短的未命名组,例如`([0-9]{4})`。
不特别推荐这种用法,因为它更容易在匹配的预期含义和视图的参数之间意外引入错误。
在任何一种情况下,建议在给定的正则表达式中仅使用一种样式。当两种样式混合使用时,将忽略任何未命名的组,并且只将命名组传递给视图函数。
## 嵌套参数
正则表达式允许嵌套参数Django将解析它们并将它们传递给视图。反转时Django将尝试填充所有外部捕获的参数忽略任何嵌套捕获的参数。考虑以下URL模式它们可选地采用页面参数
```
from django.urls import re_path
urlpatterns = [
re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]
```
两种模式都使用嵌套参数并将解析:例如, `blog/page-2/`将导致`blog_articles`与两个位置参数匹配:`page-2/`和`2`。第二个模式`comments`将匹配`comments/page-2/`关键字参数 `page_number`设置为2.在这种情况下,外部参数是非捕获参数`(?:...)`。
的`blog_articles`视图需要扭转最外捕获的参数, `page-2/`或者在这种情况下没有参数,而`comments`可与任何参数或值被反转`page_number`。
嵌套捕获的参数在视图参数和URL之间创建强耦合如下所示`blog_articles`视图接收URL`page-2/`的一部分而不是视图感兴趣的值。这种耦合在反转时更加明显因为反转我们需要传递一段URL而不是页码的视图。
根据经验,只捕获视图需要使用的值,并在正则表达式需要参数但视图忽略它时使用非捕获参数。
## URLconf搜索的内容
URLconf将搜索请求的URL作为普通的Python字符串。这不包括GET或POST参数或域名。
例如,在请求中`https://www.example.com/myapp/`URLconf将查找`myapp/`。
在请求中`https://www.example.com/myapp/?page=3`URLconf将查找`myapp/`。
URLconf不查看请求方法。换句话说所有的请求方法- `POST` 等-将被路由到相同的URL相同的功能。`GET``HEAD`
## 指定视图参数的默认值
一个方便的技巧是为视图的参数指定默认参数。这是一个示例URLconf和视图
```
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
```
在上面的示例中两个URL模式都指向同一个视图 `views.page`- 但第一个模式不会从URL捕获任何内容。如果第一个模式匹配该`page()`函数将使用它的默认参数`num``1`。如果第二个模式匹配, `page()`将使用`num`捕获的任何值。
## 表现
a中的每个正则表达式在`urlpatterns`第一次访问时编译。这使得系统非常快。
## `urlpatterns`变量的语法
`urlpatterns`应该是Python列表`path()`和/或 `re_path()`实例。
## 错误处理
当Django找不到所请求URL的匹配项时或者引发异常时Django会调用错误处理视图。
用于这些情况的视图由四个变量指定。它们的默认值应该足以满足大多数项目的需要,但可以通过覆盖它们的默认值来进一步自定义。
有关完整详细信息,请参阅有关[自定义错误视图](https://docs.djangoproject.com/en/2.0/topics/http/views/#customizing-error-views)的文档。
可以在根URLconf中设置此类值。在任何其他URLconf中设置这些变量将不起作用。
值必须是callables或字符串表示应该调用以处理手头错误条件的视图的完整Python导入路径。
变量是:
- `handler400`
- `handler403`
- `handler404`
- `handler500`
## 包括其他的URLconf
在任何时候,您`urlpatterns`都可以“包含”其他URLconf模块。这基本上是“根”一组URL低于其他URL。
例如这里是Django网站本身的URLconf的摘录。它包括许多其他URLconf
```
from django.urls import include, path
urlpatterns = [
# ... snip ...
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
# ... snip ...
]
```
每当Django遇到时`include()`它都会删除与该点匹配的URL的任何部分并将剩余的字符串发送到包含的URLconf以进行进一步处理。
另一种可能性是通过使用`path()`实例列表来包含其他URL模式 。例如考虑这个URLconf
```
from django.urls import include, path
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
path('reports/', credit_views.report),
path('reports/<int:id>/', credit_views.report),
path('charge/', credit_views.charge),
]
urlpatterns = [
path('', main_views.homepage),
path('help/', include('apps.help.urls')),
path('credit/', include(extra_patterns)),
]
```
在此示例中,`/credit/reports/`URL将由`credit_views.report()`Django视图处理 。
这可用于从重复使用单个模式前缀的URLconf中删除冗余。例如考虑这个URLconf
```
from django.urls import path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/history/', views.history),
path('<page_slug>-<page_id>/edit/', views.edit),
path('<page_slug>-<page_id>/discuss/', views.discuss),
path('<page_slug>-<page_id>/permissions/', views.permissions),
]
```
我们可以通过仅指定公共路径前缀一次并对不同的后缀进行分组来改进这一点:
```
from django.urls import include, path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]
```
## 捕获的参数
包含的URLconf从父URLconf接收任何捕获的参数因此以下示例有效
```
# In settings/urls/main.py
from django.urls import include, path
urlpatterns = [
path('<username>/blog/', include('foo.urls.blog')),
]
# In foo/urls/blog.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.blog.index),
path('archive/', views.blog.archive),
]
```
在上面的示例中,捕获的`"username"`变量按预期传递给包含的URLconf。
## 传递额外选项来查看功能
URLconfs有一个钩子允许您将额外的参数作为Python字典传递给视图函数。
该`path()`函数可以采用可选的第三个参数,该参数应该是传递给视图函数的额外关键字参数的字典。
例如:
```
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]
```
在这个例子中,对于请求`/blog/2005/`Django将调用 。`views.year_archive(request, year=2005, foo='bar')`
在联合框架中使用此技术 将元数据和选项传递给视图。
处理冲突
可以使用URL模式捕获命名关键字参数并在其额外参数字典中传递具有相同名称的参数。发生这种情况时将使用字典中的参数而不是URL中捕获的参数。
## 将额外选项传递给`include()`
同样,您可以传递额外的选项,`include()`并且包含的URLconf中的每一行都将传递额外的选项。
例如这两个URLconf集在功能上是相同的
设置一个:
```
# main.py
from django.urls import include, path
urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]
```
设置二:
```
# main.py
from django.urls import include, path
from mysite import views
urlpatterns = [
path('blog/', include('inner')),
]
# inner.py
from django.urls import path
urlpatterns = [
path('archive/', views.archive, {'blog_id': 3}),
path('about/', views.about, {'blog_id': 3}),
]
```
请注意,无论行的视图是否实际接受这些选项为有效,额外选项将*始终*传递到包含的URLconf中的*每一*行。因此只有在您确定所包含的URLconf中的每个视图都接受您传递的额外选项时此技术才有用。
## URL的反向解析
在处理Django项目时通常需要获得最终形式的URL以嵌入生成的内容视图和资产URL向用户显示的URL等或处理服务器上的导航流。方重定向等
强烈希望避免对这些URL进行硬编码这是一种费力的不可扩展且容易出错的策略。同样危险的是设计临时机制来生成与URLconf描述的设计并行的URL这可能导致生成随时间变得陈旧的URL。
换句话说需要的是DRY机制。除了其他优点之外它还允许进行URL设计的演变而无需遍历所有项目源代码来搜索和替换过时的URL。
我们可用于获取URL的主要信息是负责处理URL的视图的标识例如名称。必须参与查找正确URL的其他信息是视图参数的类型位置关键字和值。
Django提供了一个解决方案使URL映射器成为URL设计的唯一存储库。您使用URLconf提供它然后它可以在两个方向上使用
- 从用户/浏览器请求的URL开始它调用正确的Django视图提供它可能需要的任何参数以及从URL中提取的值。
- 从标识相应的Django视图以及将传递给它的参数值开始获取关联的URL。
第一个是我们在前面几节中讨论过的用法。第二个是所谓*的URL反向解析**反向URL匹配**反向URL查找*或简单的*URL反转*。
Django提供了用于执行URL反转的工具这些工具匹配需要URL的不同层
- 在模板中:使用`url`模板标记。
- 在Python代码中使用该`reverse()`函数。
- 在与处理Django模型实例的URL相关的更高级代码中该`get_absolute_url()`方法。
### 示例
再次考虑这个URLconf条目
```
from django.urls import path
from . import views
urlpatterns = [
#...
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
#...
]
```
根据这种设计对应于年度归档文件的URL *NNNN* 是`/articles/<nnnn>/`。
您可以使用以下方法在模板代码中获取这些:
```
<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>
```
或者在Python代码中
```
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
```
如果由于某种原因决定应该更改发布年度文章档案的内容的URL那么您只需要更改URLconf中的条目。
在视图具有通用性的某些情况下URL和视图之间可能存在多对一关系。对于这些情况当反转URL时视图名称不是足够好的标识符。阅读下一节了解Django为此提供的解决方案。
## 命名URL模式
要执行URL反转您需要使用**命名URL模式** 如上面的示例所示。用于URL名称的字符串可以包含您喜欢的任何字符。您不限于有效的Python名称。
命名URL模式时请选择不太可能与其他应用程序选择的名称冲突的名称。如果您调用URL模式`comment` 而另一个应用程序执行相同操作,则`reverse()`找到的URL 取决于项目`urlpatterns`列表中最后一个模式。
在URL名称上添加前缀可能是从应用程序名称派生的例如`myapp-comment`代替`comment`))可以减少冲突的可能性。
如果要覆盖视图,可以故意选择*与*其他应用程序*相同的URL名称*。例如,一个常见的用例是覆盖 `LoginView`。Django和大多数第三方应用程序的部分假定此视图具有名称的URL模式 `login`。如果你有一个自定义登录查看并给它的URL名称`login` `reverse()`将只要它在找到你的自定义视图 `urlpatterns`之后,`django.contrib.auth.urls`包括(如果这是包含在所有)。
如果参数不同您也可以对多个URL模式使用相同的名称。除URL名称外还`reverse()`匹配参数的数量和关键字参数的名称。
## URL命名空间
### 介绍
即使不同的应用程序使用相同的URL名称URL命名空间也允许您唯一地反转。对于第三方应用程序来说始终使用命名空间URL是一种很好的做法正如我们在教程中所做的那样。同样如果部署了多个应用程序实例它还允许您反向URL。换句话说由于单个应用程序的多个实例将共享命名URL因此命名空间提供了一种将这些命名URL分开的方法。
正确使用URL命名空间的Django应用程序可以针对特定站点多次部署。例如[`django.contrib.admin`]有一个 [`AdminSite`]类允许您轻松 部署多个admin实例。在后面的示例中我们将讨论在两个不同位置从教程部署民意调查应用程序的想法以便我们可以为两个不同的受众作者和发布者提供相同的功能。
URL命名空间分为两部分两部分都是字符串
- 应用命名空间
这描述了正在部署的应用程序的名称。单个应用程序的每个实例都具有相同的应用程序命名空间。例如Django的管理应用程序具有可预测的应用程序命名空间`'admin'`。
- 实例命名空间
这标识了应用程序的特定实例。实例名称空间在整个项目中应该是唯一的。但是实例名称空间可以与应用程序名称空间相同。这用于指定应用程序的默认实例。例如默认的Django管理实例的实例名称空间为`'admin'`。
命名空间URL使用`':'`运算符指定。例如,使用引用管理应用程序的主索引页面`'admin:index'`。这表示名称空间`'admin'`和命名URL `'index'`
命名空间也可以嵌套。命名URL `'sports:polls:index'`将查找`'index'`在命名空间中命名的模式,该模式`'polls'`本身在顶级命名空间中定义`'sports'`。
### 反转命名空间的URL
当给出`'polls:index'`要解析的命名空间URL例如Django将完全限定名称拆分为多个部分然后尝试以下查找
1. 首先Django寻找匹配的应用程序命名空间在本例中`'polls'`)。这将产生该应用程序的实例列表。
2. 如果定义了当前应用程序Django会查找并返回该实例的URL解析程序。可以使用 函数的`current_app`参数指定当前应用程序`reverse()`。
该`url`模板标签使用当前解决视图在当前应用程序的命名空间 [`RequestContext`]。您可以通过在[`request.current_app`]属性上设置当前应用程序来覆盖此默认值。
3. 如果没有当前的申请。Django寻找默认的应用程序实例。默认应用程序实例是具有与应用程序命名空间匹配的实例命名空间的实例在此示例中是被调用的实例。`polls``'polls'`
4. 如果没有默认的应用程序实例Django将选择最后部署的应用程序实例无论其实例名称是什么。
5. 如果提供的命名空间与步骤1 中的应用程序命名空间不匹配Django将尝试直接查找命名空间作为 实例命名空间。
如果存在嵌套命名空间则会对命名空间的每个部分重复这些步骤直到只有视图名称未解析为止。然后视图名称将被解析为已找到的命名空间中的URL。
#### 示例
要显示此解决方案策略,请考虑`polls`本教程中应用程序的两个实例的示例:一个调用`'author-polls'` ,一个调用`'publisher-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'),
...
]
```
使用此设置,可以进行以下查找:
- 如果其中一个实例是最新的 - 例如,如果我们在实例中呈现详细信息页面`'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`。
### URL命名空间和包含的URLconf
包含的URLconf的应用程序命名空间可以用两种方式指定。
首先,您可以`app_name`在包含的URLconf模块中设置属性该属性与属性处于同一级别`urlpatterns`。您必须将实际模块或对模块的字符串引用传递给它`include()`,而不是`urlpatterns`它自己的列表。
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'),
...
]
```
urls.py
```
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
]
```
定义的URL `polls.urls`将具有应用程序命名空间`polls`。
其次,您可以包含一个包含嵌入式命名空间数据的对象。如果`include()`是列表[`path()`](https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.path)或 [`re_path()`](https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.re_path)实例则该对象中包含的URL将添加到全局命名空间。但是您还可以`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模式。
可以使用`namespace`参数to 指定实例名称空间[`include()`](https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.include)。如果未指定实例名称空间则它将默认为包含的URLconf的应用程序名称空间。这意味着它也将是该命名空间的默认实例。