【问题标题】:A real example of URL NamespaceURL命名空间的一个真实例子
【发布时间】:2013-10-10 21:10:15
【问题描述】:

我正在研究 Django 文档,但是我遇到了一个我无法理解的部分:什么是在实际问题中如何使用命名空间的真实示例。我知道语法,但我不知道这样做的目的。

【问题讨论】:

  • 我现在正在学习 Django,我很担心这个 url 命名空间,甚至模板中不必要的文件夹名称。如果视图中的 url 函数有办法自动检测(上下文感知)它所在的模板,恕我直言,这应该消除这种命名空间的必要性并防止可能的冲突。

标签: django url namespaces django-views


【解决方案1】:

通常,它们用于将每个应用程序的 URL 放入自己的命名空间中。这可以防止 reverse() Django 函数和 {% url %} 模板函数返回错误的 URL,因为 URL 模式名称恰好在另一个应用程序中匹配。

我的项目级 urls.py 文件中的内容如下:

from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', 'main.views.main', name='main'),
    url(r'^login$', 'django.contrib.auth.views.login', name="login"),
    url(r'^logout$', 'django.contrib.auth.views.logout',
        {"next_page": "/"}, name="logout"),

# Admin
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

# Auto-add the applications.
for app in settings.LOCAL_APPS:
    urlpatterns += patterns('',
        url(r'^{0}/'.format(app), include(app + '.urls', namespace=app)),
    )

请注意最后一部分:这将通过我已安装的应用程序(settings.LOCAL_APPS 是我添加的仅包含我的应用程序的设置;它被添加到 INSTALLED_APPS,其中包含其他内容,例如 South),查找 @ 987654327@,并将这些 URL 导入以应用命名的命名空间,并将这些 URL 放入以应用命名的 URL 子目录中。

因此,例如,如果我有一个名为 hosts 的应用,而 hosts/urls.py 看起来像:

from django.conf.urls.defaults import *

urlpatterns = patterns('hosts.views',
    url(r'^$', 'show_hosts', name='list'),
)

现在我的views.py 可以调用reverse("hosts:list") 来获取调用hosts.views.show_hosts 的页面的URL,它看起来像"/hosts/"。模板中的{% url "hosts:list" %} 也是如此。这样我就不必担心在另一个应用程序中与名为“list”的 URL 发生冲突,也不必在每个名称前加上 hosts_

请注意,登录页面位于{% url "login" %},因为它没有指定命名空间。

【讨论】:

  • 我明白了.. 但这与将名称放入 URL 相同,对吧?做同样的工作..
  • 现在我看到了完整的答案......这太棒了......如果我做对了,你可以将命名空间与命名 URL 一起使用......这样你就不用担心你是否命名了来自同名的不同应用的两个视图...对吗?
  • 差不多。我敢肯定还有其他用途和更好的用途,但这是一个简单的例子。
  • 这样做我实际上得到了什么?通过使用诸如“myns:myname”之类的 url,我强制用户使用 namespace="myns" 包含我的应用程序。使用“myns-myname”而不依赖命名空间的真正好处是什么?
【解决方案2】:

假设您正在使用如下 url 模式
url(r'^login/',include('app_name', name='login'))

还请考虑您正在使用第三方应用程序,例如 Django-RestFramework。 使用该应用程序时,您必须在项目的 URLs conf 文件中声明以下行。

url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))

现在如果你检查rest-framework的代码,你会在urls.py文件中找到以下代码

urlpatterns = [
    url(r'^login/$', login, login_kwargs, name='login'),
    url(r'^logout/$', logout, name='logout'),
]

我们在项目中为 URL 模式使用了“登录”名称,并且 Django-rest-framework 将相同的名称用于他们的一种 URL 模式。当你使用 reverse('login') 时,Django 会感到困惑。
为了解决这类问题,我们使用命名空间。

@register.simple_tag
def optional_docs_login(request):
    """
    Include a login snippet if REST framework's login view is in the URLconf.
    """
    try:
        login_url = reverse('rest_framework:login')
    except NoReverseMatch:
        return 'log in'

命名空间的 URL 名称永远不会与其他命名空间发生冲突。
可以使用
reverse('namespace:url_name')

反转命名空间 URL 模式

【讨论】:

    【解决方案3】:

    我们还利用中间件中的命名空间来以不同的方式处理某些部分

        def process_response(self, request, response):
            try:
                if resolve(request.path).namespace == 'special_namespace':
                    response['Custom-Header'] = 'Custom-Value'
                return response
            except Resolver404:
                return response
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-08
      • 2018-08-20
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多