How do you use Django URL namespaces?

前端 未结 4 638
醉话见心
醉话见心 2021-01-31 09:09

I\'m trying to get the hang of Django URL namespaces. But I can\'t find any examples or documentation.

Here is what I have tried.

urls.py:

from d         


        
相关标签:
4条回答
  • 2021-01-31 09:35

    Here is one solution I came up with.

    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])
    

    Basically I made sure to always pass the current_app context as either "foo" or "bar", which I calculate manually by looking at the request URL. Then I use a custom tag that resolves a URL based on current_app.

    It's not very generic; "foo" and "bar" are hard-coded, and the tag can only take exactly one argument. Even with those issues fixed, this seems like a hack.

    0 讨论(0)
  • 2021-01-31 09:44

    I realize the solution below violates the DRY principal as you have to create essentially duplicate url config files for foo and bar, however I think it should work.

    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())
    

    And then for the template use this:

    {% url namespace 3 %}
    

    I haven't tested the idea of using a variable in the name section of the {% url %} tag, but I think it should work.

    0 讨论(0)
  • 2021-01-31 09:50

    I think that this isn't possible in django right now. Have a look at this message board post which references Ticket 11559. I think that you're trying to do the same thing - effectively pass an implicit parameter to the URL tag.

    Also, assuming that sub_urls is from the same app both times you should make sure app_name is the same in both cases. You should only need to change namespace.

    0 讨论(0)
  • 2021-01-31 09:56

    There seems to be no direct way to do it. I would use a similiar solution as you introduced using a template tag, though I found a more generic way. I used the fact that you can pass optional parameters in your url conf, so you can keep track of the namespace:

    #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'}),      
    )
    

    That also violates the DRY principle, but not much though :)

    Then in your view you get the namespace variable (sub_urls.py would be the same):

    #views.py
    from django import shortcuts
    
    def myvew(request, namespace):
        context = dict(namespace=namespace)
        return shortcuts.render_to_response('mytemplate.html', context)
    

    Later you just need a simple tag you pass your namespace variable and view name to:

    #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)
    

    and use it in the template (make sure to pass your view name as a string, and not as a template variable):

    <!-- mytemplate.html -->
    {% load tags %}
    {% namespace_url namespace "view1"%}
    

    Thanks for your hint btw.. I was looking for sth. like this.

    0 讨论(0)
提交回复
热议问题