前方长篇大论,深呼吸……
如果我不添加命名空间,有什么方法可以调用我的 download_document 函数? (默认情况下,它调用 3rd 方应用的 download_document 视图。
这取决于你想要做什么。如果您总是希望您的 download_document 函数在您的整个网站(甚至在 3rd-party-app 提供的页面上)都被调用,您只需将 infk 移动到 urlpatterns 的末尾main_app/urls。看起来像这样:
main_app/urls.py
================================================================================
from django.conf.urls import include, url
urlpatterns = [
url(r'^3rd-party-app/', include('3rd-party-app.urls')),
url(r'^infk/', include('infk.urls')),
]
否则,如果您试图在没有命名空间的特定实例中获取您的 download_document,这并不是特别容易。您可以创建一个始终为您的 download_document 函数生成 url 的自定义标签,但这是很多额外的工作,如果您遇到另一个名称冲突,您将不得不一次又一次地这样做,而这只是上面的一步首先对网址进行硬编码。此外,如果您计划将 infk 部署为第三方应用程序,您可能希望使用命名空间来帮助其他人避免遇到与您相同的问题。
说明
根据https://docs.djangoproject.com/en/1.11/topics/http/urls/#naming-url-patterns 的文档:
如果你调用你的 URL 模式 comment 并且另一个应用程序做同样的事情,reverse() 找到的 URL 取决于你项目的 urlpatterns 列表中的最后一个模式。
因此,如果您更改 main_app/urls.py 文件中包含的 url 的顺序,使 infk 在 3rd-party 应用程序之后,您应该获得 infk download_document。但是,这意味着您总是会得到 infk download_document,这可能会破坏您的第 3 方应用程序中的某些功能。
示例
Django 1.x
来源:https://docs.djangoproject.com/en/1.11/topics/http/urls/#reversing-namespaced-urls
您修改后的 url(r'^infk/', include('infk.urls', namespace="infk")) 创建了一个实例命名空间,如果您在整个应用程序中使用多个 infk 实例,这可能是有意义的。如果您不是(或者您计划将 infk 部署为第三方应用程序本身),您可能不需要它。无论哪种方式,我都建议您设置应用程序命名空间。
main_app/urls.py
================================================================================
from django.conf.urls import include, url
urlpatterns = [
# These are both instance namespaces. Note that although the same urls
# are being included from infk.urls for both, the final route will be
# different.
url(r'^infk-instance1/', include('infk.urls', namespace='infk-instance1')),
url(r'^infk-instance2/', include('infk.urls', namespace='infk-instance2')),
# The 3rd-party app your url and reverse functions are colliding with.
url(r'^3rd-party-app/', include('3rd-party-app.urls')),
]
infk/urls.py
================================================================================
from django.conf.urls import url
from . import views
# This is the application namespace. I recommend setting this regardless of
# whether you use instance namespaces.
app_name = 'infk'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.download_document(), name='download_document'),
]
实例命名空间
实例命名空间会这样调用:
infk/foo_template.html
================================================================================
...
<!-- In this case, {% url 'infk-instance1:download_document' document.id %}
will return /infk-instance1/<document.id>-->
<a href="{% url 'infk-instance1:download_document' document.id %}">Download Document</a>
...
ingk/foo_template.html
================================================================================
...
<!-- In this case, {% url 'infk-instance2:download_document' document.id %}
will return /infk-instance2/<document.id>-->
<a href="{% url 'infk-instance2:download_document' document.id %}">Download Document</a>
...
如果需要,您应该仍然可以获取 3rd-party download_document 网址。请注意,为了使其正常工作,必须在 infk.urls 之后包含 3rd-party-app.urls。
ingk/foo_template.html
================================================================================
...
<!-- In this case, {% url 'download_document' document.id %}
will return /3rd-party-app/<document.id>-->
<a href="{% url 'download_document' document.id %}">Download Document</a>
...
应用命名空间
应用程序命名空间的行为取决于是否为应用程序定义了实例命名空间,以及调用的视图是否定义了 current_app。如果您使用上面定义了应用程序和实例命名空间的示例,那么在 {% url %} 标记中使用应用程序命名空间可能会返回不一致的结果。 (更多信息请参见https://docs.djangoproject.com/en/1.11/topics/http/urls/#reversing-namespaced-urls)
为了便于解释,我假设您没有使用 infk 应用程序的多个实例。您的 main_app/urls.py 可能如下所示:
main_app/urls.py
================================================================================
from django.conf.urls import include, url
urlpatterns = [
# No instance namespaces
url(r'^infk/', include('infk.urls')),
url(r'^3rd-party-app/', include('3rd-party-app.urls')),
]
应用命名空间是这样调用的:
infk/foo_template.html
================================================================================
...
<!-- In this case, {% url 'infk:download_document' document.id %}
will return /infk/<document.id>-->
<a href="{% url 'infk:download_document' document.id %}">Download Document</a>
...
而且,假设在 infk 之后安装了 3rd-party 应用程序,您的 3rd-party 应用程序的 download_document 仍然可以这样调用:
ingk/foo_template.html
================================================================================
...
<!-- In this case, {% url 'download_document' document.id %}
will return /3rd-party-app/<document.id>-->
<a href="{% url 'download_document' document.id %}">Download Document</a>
...
Django >=2.x
来源:https://docs.djangoproject.com/en/dev/topics/http/urls/#term-application-namespace
解析器的工作原理与上述基本相同;但是,不要在 urls.py 文件中使用 url(),而是使用 path() 或 re_path()。