我正试图抓住Django URL namespaces。但我找不到任何例子或文件。
这是我尝试过的。
urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^foo/', include('sub_urls', namespace='foo', app_name='foo')),
(r'^bar/', include('sub_urls', namespace='bar', app_name='bar')),
)
sub_urls.py:
from django.conf.urls.defaults import patterns, url
from views import view1
urlpatterns = patterns('views',
url(r'^(?P<view_id>\d+)/$', view1, name='view1')
)
views.py:
from django.shortcuts import render_to_response
def view1(request, view_id):
return render_to_response('view1.html', locals())
在view1.html中,{%url foo:view1 3%}输出/ foo / 3,{%url bar:view1 3%}输出/ bar / 3。无论我是浏览/ foo / X还是/ bar / X,都是如此。
我想要的是能够浏览到/ foo / X或/ bar / X,并且{%url view1 3%}分别输出/ foo / 3或/ bar / 3。
答案 0 :(得分:6)
似乎没有直接的方法来做到这一点。我会使用一个类似的解决方案,因为你使用模板标签,虽然我发现了一种更通用的方式。我使用了你可以在url conf中传递可选参数这一事实,因此你可以跟踪命名空间:
#urls.py
from django.conf.urls import defaults
urlpatterns = defaults.patterns('',
defaults.url(r'^foo/', include('sub_urls', namespace='foo', app_name='myapp'),
kwargs={'namespace':'foo'}),
defaults.url(r'^bar/', include('sub_urls', namespace='bar', app_name='myapp'),
kwargs={'namespace':'bar'}),
)
这也违反了DRY原则,但并不多:)
然后在您的视图中,您将获得命名空间变量(sub_urls.py将是相同的):
#views.py
from django import shortcuts
def myvew(request, namespace):
context = dict(namespace=namespace)
return shortcuts.render_to_response('mytemplate.html', context)
稍后您只需要一个简单的标记,将命名空间变量和视图名称传递给:
#tags.py
from django import template
from django.core import urlresolvers
register = template.Library()
def namespace_url(namespace, view_name):
return urlresolvers.reverse('%s:%s' % (namespace, view_name, args=args, kwargs=kwargs)))
register.simple_tag(namespace_url)
并在模板中使用它(确保将视图名称作为字符串传递,而不是作为模板变量传递):
<!-- mytemplate.html -->
{% load tags %}
{% namespace_url namespace "view1"%}
谢谢你的提示顺便说一下......我在寻找某事。像这样。
答案 1 :(得分:3)
我认为现在这在django中是不可能的。请查看引用message board post的Ticket 11559。我认为您正在尝试做同样的事情 - 有效地将隐式参数传递给URL标记。
此外,假设sub_urls
两次来自同一个应用,您应该确保app_name
在两种情况下都相同。您应该只需要更改命名空间。
答案 2 :(得分:0)
这是我提出的一个解决方案。
views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
def render_response_context(view, locals):
request = locals["request"]
app = "bar" if request.META["PATH_INFO"].lower().startswith("/bar") else "foo"
return render_to_response(view, locals,
context_instance=RequestContext(request, current_app=app))
def view1(request, view_id):
return render_response_context('view1.html', locals())
view1.html:
{% load extras %}
{% namespace_url view1 3 %}
extras.py:
from django import template
from django.core.urlresolvers import reverse
register = template.Library()
@register.tag
def namespace_url(parser, token):
tag_name, view_string, arg1 = token.split_contents()
return NamespaceUrlNode(view_string, arg1)
class NamespaceUrlNode(template.Node):
def __init__(self, view_string, arg1):
self.view_string = view_string
self.arg1 = arg1
def render(self, context):
return reverse("%s:%s" % (context.current_app, self.view_string), args=[self.arg1])
基本上我确保始终将current_app上下文作为“foo”或“bar”传递,我通过查看请求URL手动计算。然后我使用自定义标记解析基于current_app的URL。
它不是很通用; “foo”和“bar”是硬编码的,标签只能采用一个参数。即使修复了这些问题,这似乎也是一种黑客攻击。
答案 3 :(得分:0)
我意识到下面的解决方案违反了DRY原则,因为你必须为foo和bar创建基本上重复的url配置文件,但我认为它应该可以工作。
urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^foo/', include('sub_urls_foo')),
(r'^bar/', include('sub_urls_bar')),
)
sub_urls_foo.py:
from django.conf.urls.defaults import patterns, url
from views import view1
urlpatterns = patterns('views',
url(r'^(?P<view_id>\d+)/$', view1, 'view1_foo', {'namespace': 'view1_foo'})
)
sub_urls_bar.py:
from django.conf.urls.defaults import patterns, url
from views import view1
urlpatterns = patterns('views',
url(r'^(?P<view_id>\d+)/$', view1, 'view1_bar', {'namespace': 'view1_bar'})
)
views.py:
from django.shortcuts import render_to_response
def view1(request, view_id, namespace):
return render_to_response('view1.html', locals())
然后对于模板使用此:
{% url namespace 3 %}
我没有在{%url%}标记的名称部分测试使用变量的想法,但我认为它应该可行。