如何在Django命名空间可重用应用中进行反向URL搜索
假设我在项目中引入了一个可以重复使用的应用程序,并且这个应用程序有自己的命名空间:
urlpatterns = patterns('',
# ella urls
url('^ella/', include('ella.core.urls', namespace="ella")),
)
现在,Ella应用程序的链接看起来是这样的:
urlpatterns = patterns( '',
url( r'^(?P<category>[a-z0-9-/]+)/$', category_detail, name="category_detail" ),
# object detail
url( r'^(?P<category>[a-z0-9-/]+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<content_type>[a-z0-9-]+)/(?P<slug>[a-z0-9-]+)/$',
object_detail, name="object_detail" )
)
现在,调用 {% url ella:category_detail category="cat" %}
是可以正常工作的。但是,当某个对象想要生成它的详细信息链接时,它调用的是:
from django.core.urlresolvers import reverse
url = reverse('object_detail', kwargs={'required' : 'params'})
这个链接是无法正常工作的,除非重写成:
from django.core.urlresolvers import reverse
url = reverse('ella:object_detail', kwargs={'required' : 'params'})
所以,如果我理解得没错的话,把可重复使用的应用程序放入命名空间会导致该应用程序内部的所有 reverse() 函数失效。
这是真的吗?我漏掉了什么吗?有没有解决办法?
3 个回答
在Django 1.8中,你可以写类似这样的代码:
url = reverse('%s:object_detail' % request.resolver_match.namespace, kwargs={'required' : 'params'})
request.resolver_match.namespace
是一个字符串,它包含了当前正在运行的视图的命名空间。
URL命名空间可以通过两种方式来指定。
首先,你可以在构建URL模式时,把应用程序和实例的命名空间作为参数传递给include()。比如说:
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
这段内容来自于 http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces。
试着把 include('ella.core.urls', namespace="ella")
改成 include('ella.core.urls', namespace="ella", app_name="ella")
。我不能保证这一定有效,但值得一试。
因为你使用了命名空间的URL配置,所以在反向解析的时候,需要提到namespace:view-name的格式,这样才能正确地找到对应的视图,特别是在视图中使用的时候。
不过,如果你想避免这样做,你也可以把namespace/appname作为current_app参数传递。其实在模板中有好几种方法可以指定current_app,但如果你在视图中,就需要像你之前那样直接写死,或者把它传给current_app参数。
url = reverse('object_detail',
kwargs={'foo':'bar'},
current_app=app_name_or_name_space)
参考: http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse