Aks
Aks

Reputation: 395

Django 2.0 | include multiple urls conf namespace

This "problem" is quite related to : django 2.0 url.py include namespace="xyz"

The previous dev used Django 1.9 (or maybe even before) but we are now migrating to Django 2.0. We got 3 sites on the same project, all with only 1 specific URLS Conf

### MAIN PROJECT REFERENCING ALL SITES ###
###         Nothing changed here       ###
from django.conf import settings
from django.conf.urls import url, include
from django.contrib import admin
from django.conf.urls.static import static
from django.urls import path
from frontend import urls as frontend_urls
from search import urls as search_urls
from international import urls as international_urls

# Customisation admin
admin.site.site_header = 'INT - ADMIN'

temppatterns = [   
# Admin Sites
url(r'^admin/', admin.site.urls),
# Organisation Sites
url(r'^frontend/', include(frontend_urls)),
# 1st Platform
url(r'^search/', include(search_urls)),
# 2nd Platform
url(r'^international/', include(international_urls)),
]
urlpatterns = temppatterns + static(settings.MEDIA_URL, 
document_root=settings.MEDIA_ROOT)

Here is the previous frontend URLs CONF

FRONTEND_PATTERNS = [
    url(r'^conseiller$', views.GuidanceView.as_view(), name='guidance'),
    .......
    url(r'^contact$', views.ContactView.as_view(), name='contact'),
    url(r'^$', views.HomeView.as_view(), name='home'),
]

COMPANY_PATTERNS = [
    url(r'^companydetail/(?P<slug>[-\w]+)/$',
        views.MemberLgView.as_view(),
        name='lg-detail'),
    url(r'^asso/orga/(?P<slug>[-\w]+)/$',
        views.MemberOrgView.as_view(),
        name='org-detail'),
]

CONTENT_PATTERNS = [
    .......
]

EVENT_PATTERNS = [
    .......
]

REDIRECT_PATTERNS = [
    url(r'^actualite/(?P<pk>\d+)/(?P<slug>[-\w]+)/$',
        views.OldBlogRedirectView.as_view(),
        name='blog-redirect'),
    .......
    url(r'^ressources$',
        RedirectView.as_view(
            url=reverse_lazy('frontend:doc'), permanent=True)),
]

urlpatterns = [
    url(r'^', include(FRONTEND_PATTERNS, namespace='frontend')),
    url(r'^', include(COMPANY_PATTERNS, namespace='companies')),
    url(r'^', include(CONTENT_PATTERNS, namespace='contents')),
    url(r'^', include(REDIRECT_PATTERNS, namespace='redirects')),
    url(r'^', include(EVENT_PATTERNS, namespace='events')),
] + static(
    settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

But now, the include with namespace seems to be deprecated. So we changed few things in this docs

# Added app_name
app_name="frontend"

# Deleting namespace - deprecated
urlpatterns = [
    re_path(r'^', include(FRONTEND_PATTERNS)),
    re_path(r'^', include(COMPANY_PATTERNS)),
    re_path(r'^', include(CONTENT_PATTERNS)),
    re_path(r'^', include(REDIRECT_PATTERNS)),
    re_path(r'^', include(EVENT_PATTERNS)),
] + static(
    settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

But now we got this error at 127.0.0.1:8000/frontend :

NoReverseMatch at /frontend/ 'companies' is not a registered namespace

on

'companies:%s-detail' % self.route_name, args=(self.slug, )) 

Which is logic. So I tried to configure URLs like this

re_path(r'^', include(COMPANY_PATTERNS, namespace='companies')),

But got

django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.

Reading the doc, it appears I should use

re_path(r'^', include((COMPANY_PATTERNS, app_name), namespace='companies')),

So let's go, but we are back to this :

NoReverseMatch at /frontend/ 'companies' is not a registered namespace

So I sat and tried to add frontend: before companies which work !

'frontend:companies:%s-detail' % self.route_name, args=(self.slug, )) 

However, this is a really big big work of refactorisation, is there a better way to include URLs and set a dedicated namespace ?

Upvotes: 0

Views: 2944

Answers (2)

CoffeeBasedLifeform
CoffeeBasedLifeform

Reputation: 2921

Have you tried adding the namespace to the pattern lists?

REDIRECT_PATTERNS = ( [
        url(r'^actualite/(?P<pk>\d+)/(?P<slug>[-\w]+)/$',
            views.OldBlogRedirectView.as_view(),
            name='blog-redirect'),
        .......
        url(r'^ressources$',
            RedirectView.as_view(
                url=reverse_lazy('frontend:doc'), permanent=True)),
    ] , 'redirects') 

...

urlpatterns = [
    re_path(r'^', include(REDIRECT_PATTERNS)),
    ...

I assume, this is what your first ImproperlyConfigured exception complains about.
There is another way (shown here in the answer of py_dude); both are explained in the docs.

Upvotes: 1

py_dude
py_dude

Reputation: 832

For Django 2.0 this should look like:

temppatterns = [   
# Admin Sites
path('admin/', admin.site.urls),
# Organisation Sites
path('frontend/', include('frontend.urls')),
# 1st Platform
path('search/', include('search.urls')),
# 2nd Platform
path('international/', include('international.urls')),
]

And so on... Look at url() functions are replaced with path() and regexp strings replaced with strings

Did you read the docs?

Also, see the include() docs to know, what object could be passed to this function

Upvotes: 1

Related Questions