it-swarm.com.ru

Как вы используете пространства имен Django URL?

Я пытаюсь освоить пространства имен URL 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%} выводит/bar/3. Это верно, независимо от того, просматриваю ли я/foo/X или/bar/X.

Я хочу иметь возможность просматривать/foo/X или/bar/X и получать {% url view1 3%} вывод либо/foo/3, либо/bar/3 соответственно.

29
Chase Seibert

Я думаю, что сейчас это невозможно в Джанго. Посмотрите на это сообщение на доске объявлений какие ссылки Билет 11559 . Я думаю, что вы пытаетесь сделать то же самое - эффективно передать неявный параметр в тег URL. 

Кроме того, предполагая, что sub_urls из одного и того же приложения оба раза, вы должны убедиться, что app_name одинаков в обоих случаях. Вам нужно только изменить пространство имен.

3
Mystic

Кажется, нет прямого способа сделать это. Я бы использовал похожее решение, как вы ввели, используя тег шаблона, хотя я нашел более общий способ. Я использовал тот факт, что вы можете передавать необязательные параметры в вашем 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"%}

Спасибо за вашу подсказку, кстати .. Я искал что-то. как это.

6
Torsten Engelbrecht

Вот одно решение, которое я придумал.

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» жестко запрограммированы, и тег может принимать только один аргумент. Даже с этими проблемами, похоже, взломать.

0
Chase Seibert

Я понимаю, что приведенное ниже решение нарушает принцип 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%}, но думаю, что это должно сработать.

0
Steven Potter