Django URL名称空间 - 模板必须知道其名称空间?

时间:2015-05-27 22:12:21

标签: django url namespaces

我一直在修补(我的第一个)Django项目,该项目最初是使用Django 1.6,最近刚刚转移到Django 1.8。我也一直在通过Django Patterns& amp;最佳实践,了解我应该如何构建它: - )

我的项目有几个子应用和一个典型的主要urls.py,其中包含以下行:

 (r'', include('noc.apps.frontpage.urls')),

在每个应用中,我已使用应用名称为所有网址名称添加前缀,例如: frontpage_edit_page并在整个模板中使用{% url %}来引用视图。

然后我读到了URL命名空间,并认为我可以去除我的URL名称。正如我第一次解释的那样,如果我在主urls.py中为每个include()添加一个名称空间,那么一切都会像以前那样起作用,因为所引用的URL名称都将由' local'应用程序。但它似乎并没有这样做。

在主urls.py中使用它:

(r'', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),

这在app urls.py中:

 url(r'^frontpage/edit/(?P<slug>[A-Za-z0-9]+)$', views.edit_page, name='front_page_edit_page'),
在该应用内的模板中

{% url 'front_page_edit_page' slug=page.slug %},我得到了一个N​​oReverseMatch异常,尝试了0个网址。

我能找到的所有示例都在讨论使用命名空间前缀URL frontpage:front_page_edit_page但是1)这对URL名称上的先前应用前缀有何改进? 2)你怎么能拥有同一个应用程序的两个实例,这应该是一个好处...所以我假设这是用于链接应用程序之间的,而不是 应用程序内。

那么我错过了什么?我是否还需要在视图函数中嵌入app_name或命名空间?确实,如果我的所有URL名称都用命名空间作为前缀,即使在应用程序中也是如此,我会得到一个渲染页面,但它似乎打败了这一点。

3 个答案:

答案 0 :(得分:4)

您的意图确实是将名称空间添加到URL标记中;

ScriptControl

但是更好的做法是构建像你这样的主项目URls文件;

{% url 'frontpage:edit_page' slug='SLUG' %}

这样您就可以在主URL文件中指定每个应用的路径,并避免重复;

urlpatterns = patterns(
    '',
    url(r'^admin/', include(admin.site.urls)),  # NOQA
    url(r'frontpage', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),

通过这种方式,您可以为所有应用引入RESTful网址结构,以便您最终获得类似的内容;

urlpatterns = patterns(
    'noc.apps.frontpage.views',
    url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit_page', name='edit_page'),

您的所有应用都可以遵循类似的结构;

urlpatterns = patterns(
    '',
    url(r'^admin/', include(admin.site.urls)),  # NOQA
    url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),
    url(r'contact/', include('noc.apps.contact.urls', namespace='contact', app_name='contact')),
    url(r'myapp/', include('noc.apps.myapp.urls', namespace='myapp', app_name='myapp')),

使用顶级命名空间可以实现urlpatterns = patterns( 'noc.apps.contact.views', url(r'^$', 'index', name='index'), url(r'^add/$', 'add', name='add'), url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit', name='edit'), urlpatterns = patterns( 'noc.apps.myapp.views', url(r'^$', 'index', name='index'), url(r'^add/$', 'add', name='add'), url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit', name='edit'), 的多个实例;

frontpage

这样你就可以定位顶级实例命名空间,然后是这样的app命名空间;

urlpatterns = patterns(
    '',
    url(r'^admin/', include(admin.site.urls)),  # NOQA
    url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage1', app_name='frontpage')),
    url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage2', app_name='frontpage')),

但是如果你想保持你的模板链接更通用我相信你可以省略顶级命名空间,django将解析为你必须添加到请求对象的当前应用程序。这在Reversing Namespaced URLs

的末尾详细说明

答案 1 :(得分:0)

试试这个

(r'', include('noc.apps.frontpage.urls', namespace = 'abc')),

然后在你的模板中:

{% url 'abc:frontpage:front_page_edit_page' slug=page.slug %}

答案 2 :(得分:0)

Django 2.2.2 这对我有用:

# project urls.py
# DjpollsConfig is my app config
from djpolls.apps import DjpollsConfig
djpolls_app_name = DjpollsConfig.name

urlpatterns = [
    path(djpolls_app_name, include('djpolls.urls', namespace='djpolls_app_name'))
]

# app urls.py
from django_proj.urls import djpolls_app_name
app_name = djpolls_app_name

# app template
{% url 'djpolls_app_name:detail' question.id %}

希望有帮助!