GetOffMyLawn
GetOffMyLawn

Reputation: 1442

Django URLs and include() - how do you differentiate between 2 urls with the same "name" in 2 separate apps?

I have 2 apps in my project, "landing" and "news". Right now, I have the URLs configured like this:

project/urls.py:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('landing.urls')),
    path('news/', include('news.urls')),
]

project/landing/urls.py:

urlpatterns = [
    path('', landing_view, name='landing'),
]

project/news/urls.py:

urlpatterns = [
    path('', news_view, name='news'),
]

navbar link hrefs:

href="{% url 'landing' %}"
href="{% url 'news' %}"

I believe this setup is pretty standard and it all works fine so far. What I don't like is that this setup depends on each app having unique names for each url path. I'd like to be able to specify the app when referencing a URL name. That way I wouldn't have to worry about accidentally re-using the same name for a url in different apps.

The documentation mentions using app_name/namespace parameters, but they don't give any examples for how to reference a url in the url tag.

I've tried something like this:

project/urls.py:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('landing.urls', namespace='landing', app_name='landing')),
    path('news/', include('news.urls', namespace='news', app_name='news')),
]

project/landing/urls.py:

urlpatterns = [
    path('', landing_view, name='index'),
]

project/news/urls.py:

urlpatterns = [
    path('', news_view, name='index'),
]

navbar link hrefs:

href="{% url 'landing:index' %}"
href="{% url 'news:index' %}"

But I get this error:

    path('', include('landing.urls', namespace='landing', app_name='landing')),
TypeError: include() got an unexpected keyword argument 'app_name'

Take out the app_name parameter, and I get a conflicting error:

path('', include('landing.urls', namespace='landing')),
  File "D:\Dev\my_site\venv\lib\site-packages\django\urls\conf.py", line 38, in include
    raise ImproperlyConfigured(
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.

Am I misusing the namespace/app_name functionality or is there something else I'm missing?

Upvotes: 2

Views: 1090

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

You should specify different namespaces, and app_name=… is not a valid parameter for include(…). You in fact do not need a namespace in the first place, you can in both urls.py specify an app_name:

# landing/urls.py

app_name = 'landing'

urlpatterns = [
    path('', landing_view, name='index'),
]

and:

# news/urls.py

app_name = 'news'

urlpatterns = [
    path('', news_view, name='index'),
]

then you can import these with:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('landing.urls')),
    path('news/', include('news.urls')),
]

then you can refer to the app_name with:

href="{% url 'landing:index' %}"
href="{% url 'news:index' %}"

If you want to override the namespace of an include, you can specify this with the namespace=… parameter, so:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('landing.urls', namespace='otherlanding')),
    path('news/', include('news.urls')),
]

then you thus rewrite this to:

href="{% url 'otherlanding:index' %}"
href="{% url 'news:index' %}"

Upvotes: 3

Related Questions