Как вы используете пространства имен URL-адресов Django?
Я пытаюсь найти область имен Django. Но я не могу найти никаких примеров или документации.
Вот что я пробовал.
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%} выходы/бар/3. Это верно, если я просматриваю /foo/X или/bar/X.
Я хочу, чтобы иметь возможность просматривать /foo/X или/bar/X и выводить {% url view1 3%} на /foo/ 3 или/bar/3 соответственно.
Ответы
Ответ 1
Я думаю, что это невозможно в джанго прямо сейчас. Взгляните на это сообщение на доске сообщений, которое ссылается Ticket 11559. Я думаю, что вы пытаетесь сделать то же самое - эффективно передавать неявный параметр в тег URL.
Кроме того, если предположить, что sub_urls
из одного и того же приложения оба раза, вы должны убедиться, что app_name
в обоих случаях одинаково. Вам нужно только изменить пространство имен.
Ответ 2
Кажется, нет прямого способа сделать это. Я бы использовал аналогичное решение, которое вы использовали с помощью тега шаблона, хотя я нашел более общий способ. Я использовал тот факт, что вы можете передавать необязательные параметры в вашем 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"%}
Спасибо за подсказку btw.. Я искал sth. как это.
Ответ 3
Вот одно из решений, которое я придумал.
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-адрес запроса. Затем я использую специальный тег, который разрешает URL-адрес на основе current_app.
Это не очень общий; "foo" и "bar" жестко закодированы, и тег может принимать только один аргумент. Даже если эти проблемы исправлены, это кажется взломом.
Ответ 4
Я понимаю, что нижеприведенное решение нарушает принцип DRY, поскольку вам нужно создать по существу дублирующие конфигурационные файлы url для foo и bar, однако я думаю, что он должен работать.
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%}, но я думаю, что она должна работать.