pythondjangodjango-urls

"warning urls.W005 URL namespace isn't unique" -- what does it mean? (Django)


I am having trouble understanding the following warning. I have a namespace called "v1" and I am using these namespaces to determine versioning in my API (using django rest framework). So, I have paths like these:

/v1/accounts/me
/v1/listings

Here is the URLs configuration (project/urls.py):

urlpatterns = [
    path('admin/', admin.site.urls),
    path('v1/accounts/', include('accounts.urls', namespace='v1')),
    path('v1/listings/', include('listings.urls', namespace='v1'))
]

accounts/urls.py

app_name = 'accounts'

urlpatterns = [
    url(r'^token/$', views.obtain_auth_token, name='obtain_token'),
    url(r'^me/$', my_account, name='my_account'),
]

listings/urls.py

app_name = 'listings'

urlpatterns = [
    path('', recent_listings, name='recent_listings')
]

Everything works as expected. All urls are dispatched. Versioning works. However, I keep getting the following error:

?: (urls.W005) URL namespace 'v1' isn't unique. You may not be able to reverse all URLs in this namespace

I know it is a warning and I might be able to suppress it; however, I want to understand why this is happening. Based on my URLconf and this warning, it seems like there cannot be multiple namespaced paths as "siblings." They need to be children of one namespaced path (e.g "v1"). If my understanding is correct, how am I supposed to create this URL configuration.


Solution

  • Basically what happens is that, namespace plays a significant role on reverse finding the url. For example:

    In your example reverse('v1:obtain_token') will return /v1/accounts/token/. Lets say you have two urls with same name in accounts and listings, then you might not be able to find accounts url in reverse query. That is why the warning is for. Better if you use different namespaces for each include. In you case, it should be:

    path('v1/accounts/', include('accounts.urls', namespace='accounts')),
    path('v1/listings/', include('listings.urls', namespace='listings'))
    

    Please read the documentations for more details.

    Update

    you can do the versioning like this:

    path('accounts/', include('accounts.urls', namespace='accounts')),  # accounts url 
    

    inside accounts app:

    path('v1/token/', views.obtain_auth_token, name='obtain_token_v1'),
    path('v2/token/', views.obtain_auth_token2, name='obtain_token_v2'),
    ...