30

我正在尝试掌握Django URL namespaces的窍门。但我找不到任何示例或文档。

这是我尝试过的。

网址.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')
)

视图.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。

4

4 回答 4

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"%}

顺便说一句,谢谢你的提示。我在找某事。像这样。

于 2010-09-30T08:25:33.740 回答
3

我认为这在 django 中是不可能的。看看这个引用Ticket 11559的留言板帖子。我认为您正在尝试做同样的事情 - 有效地将隐式参数传递给 URL 标记。

此外,假设sub_urls两次都来自同一个应用程序,您应该确保app_name在两种情况下都是相同的。您应该只需要更改命名空间。

于 2010-01-29T19:22:55.403 回答
0

我意识到下面的解决方案违反了 DRY 原则,因为您必须为 foo 和 bar 创建基本上重复的 url 配置文件,但是我认为它应该可以工作。

网址.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'})
)

视图.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 %} 标签的名称部分使用变量的想法,但我认为它应该可以工作。

于 2010-01-15T02:36:25.327 回答
-1

这是我想出的一种解决方案。

视图.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 %}

额外的.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”是硬编码的,标签只能接受一个参数。即使解决了这些问题,这似乎也是一种黑客行为。

于 2009-12-17T04:35:28.257 回答