Search code examples
pythondjangonamespacesurlconf

Django reusable app url namespace issue


I have a Django project, training and an app inside this project, tests. The folder structure looks like this:

django-training
    tests
        urls.py
    training
        urls.py

Inside training/urls.py I have this pattern defined:

url(r'^tests/', include('tests.urls', namespace='tests'))

And inside tests/urls.py I have these patterns defined:

url(r'^$', index, name='index'),
url(r'^(\d+)/$', view, name='view'),
url(r'^give-up/$', give_up, name='give_up'),
url(r'^(\d+)/result/$', result, name='result')

Everything works fine.

But, what if I want to package the tests app as a reusable app that works in any Django project? What should I do with the URL patterns?

I created a tests/settings.py file and changed the ROOT_URLCONF config var to point to tests/urls.py. But this won't work, as this error will arise:

Traceback (most recent call last):
File "/home/user/.virtualenvs/clean2/local/lib/python2.7/site-packages/tests/tests.py", line 173, in testContext
    response = self.client.get(reverse('tests:view', args=(1,)))
File "/home/user/.virtualenvs/clean2/local/lib/python2.7/site-packages/django/core/urlresolvers.py", line 492, in reverse
key)
NoReverseMatch: u'tests' is not a registered namespace

The error is quite logic, since reverse needs the namespace to be defined (tests, that is).

My question is: how and where shall I define this namespace for the reusable app so that URLs will work independent of the Django project the app is installed in?


Solution

  • I've found a quick solution to this problem in the Django manual.

    In my tests/urls.py I've included the test namespace as so:

    test_patterns = patterns('',
        url(r'^$', index, name='index'),
        url(r'^(\d+)/$', view, name='view'),
        url(r'^give-up/$', give_up, name='give_up'),
        url(r'^(\d+)/result/$', result, name='result'),
    )
    
    urlpatterns = patterns('',
        url(r'^tests/', include(test_patterns, namespace='tests')),
    )
    

    URL reverse problems are now solved and everything works as expected.