Defining nested namespaces in a URLConf, for reversing Django URLs -- does anyone have a cogent example? Defining nested namespaces in a URLConf, for reversing Django URLs -- does anyone have a cogent example? python python

Defining nested namespaces in a URLConf, for reversing Django URLs -- does anyone have a cogent example?


It works rather intuitively. include a urlconf that has yet another namespaced include will result in nested namespaces.

## urls.pynested2 = patterns('',   url(r'^index/$', 'index', name='index'),)nested1 = patterns('',   url(r'^nested2/', include(nested2, namespace="nested2"),   url(r'^index/$', 'index', name='index'),)   urlpatterns = patterns('',   (r'^nested1/', include(nested1, namespace="nested1"),)reverse('nested1:nested2:index') # should output /nested1/nested2/index/reverse('nested1:index') # should output /nested1/index/

It's a great way to keep urls organized. I suppose the best advice I can give is to remember that include can take a patterns object directly (as in my example) which lets you use a single urls.py and split views into useful namespaces without having to create multiple urls files.


UPDATE 2 (2019-10-09)

As eugene comments, UPDATE 1 no longer works for more recent versions of Django, which require an app_name to be defined in a urls.py when it's being included.

On GitHub I've created a Django project (myproject) with a couple of apps (products and books) to demonstrate how this is done to create nested namespaces. In summary, the various urls.py look like this:

# myproject/urls.pyfrom django.urls import include, pathfrom products import urls as products_urlsfrom products import viewsurlpatterns = [    path("", views.site_home, name="home"),    path("products/", include(products_urls, namespace="products"),)]
# products/urls.pyfrom django.urls import include, pathfrom books import urls as books_urlsfrom . import viewsapp_name = "products"urlpatterns = [    path("", views.index, name="product_index"),    path("books/", include(books_urls, namespace="books")),]
# books/urls.pyfrom django.urls import pathfrom . import viewsapp_name = "books"urlpatterns = [    path("", views.index, name="book_index"),    path("<slug:book_slug>/", views.detail, name="book_detail"),]

So you can use these nested URL names like this:

reverse("products:books:book_index")# '/products/books/'reverse("products:books:book_detail", kwargs={"book_slug": "my-book"})# '/products/books/my-book/'

UPDATE 1

Django 2.0 introduced two relevant changes. First, the urls() function is now in django.urls, so the first line of the urls.py example above would be:

from django.urls import include, url

Second, it introduce the path() function as a simpler alternative for paths that don't require a regular expression. Using that, the example urls.py would be like this:

from django.urls import include, pathnested2 = [   path('index/', 'index', name='index'),]   nested1 = [   path('nested2/', include(nested2, namespace='nested2')),   path('index/', 'index', name='index'),]   urlpatterns = [   path('nested1/', include(nested1, namespace='nested1')),]

ORIGINAL ANSWER

While Yuji's answer is correct, note that django.conf.urls.patterns no longer exists (since Django 1.10) and plain lists are used instead.

The same example urls.py should now be like this:

from django.conf.urls import include, urlnested2 = [   url(r'^index/$', 'index', name='index'),]   nested1 = [   url(r'^nested2/', include(nested2, namespace='nested2')),   url(r'^index/$', 'index', name='index'),]   urlpatterns = [   url(r'^nested1/', include(nested1, namespace='nested1')),]   

And still used like:

reverse('nested1:nested2:index') # should output /nested1/nested2/index/reverse('nested1:index') # should output /nested1/index/