How do you use Django URL namespaces?

Chase Seibert picture Chase Seibert · Dec 17, 2009 · Viewed 25.6k times · Source

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

In view1.html, {% url foo:view1 3 %} outputs /foo/3, and {% url bar:view1 3 %} outputs /bar/3. This holds true whether I browse to /foo/X or /bar/X.

What I want is to be able to browse to /foo/X or /bar/X, and have {% url view1 3 %} output either /foo/3 or /bar/3, respectively.

Answer

Torsten Engelbrecht picture Torsten Engelbrecht · Sep 30, 2010

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.