Django namespacing still produces collision

I have two apps using same names in my django project. After configuring namespacing, I still get collision. For example when I visit localhost:8000/nt/, I get template from the other app. (localhost:8000/se/ points to the right template).

I must have missed something. Here is the code:

dj_config/urls.py

urlpatterns = [
    path("se/", include("simplevent.urls", namespace="se")),
    path("nt/", include("nexttrain.urls", namespace="nt")),
    # ...
]

dj_apps/simplevent/urls.py

from . import views

app_name = "simplevent"

urlpatterns = [
    path(route="", view=views.Landing.as_view(), name="landing")
]

dj_apps/nexttrain/urls.py

from django.urls import path
from . import views

app_name = "nexttrain"

urlpatterns = [
    path(route="", view=views.Landing.as_view(), name="landing"),
]

dj_config/settings.py

INSTALLED_APPS = [
    "dj_apps.simplevent.apps.SimpleventConfig",
    "dj_apps.nexttrain.apps.NexttrainConfig",
    # ...
]

TEMPLATES = [
    {
        # ....
        "DIRS": [],
        "APP_DIRS": True, 
    }

Both views will have the same code:

class Landing(TemplateView):
    template_name = "landing.html"

Templates are located in:

  • dj_apps/simplevent/templates/landing.html
  • dj_apps/nexttrain/templates/landing.html

Note that reversing order of apps in INSTALLED_APPS will reverse the problem (/se will point to nexttrain app).

The usual structure that your template backend expects when looking for template files is: <your app>/templates/<your app>/some_template.html, so your template paths should be:

  • dj_apps/simplevent/templates/simplevent/landing.html
  • dj_apps/nexttrain/templates/nexttrain/landing.html

Django does it like this because when collectstatic is run, it practically copies the files from templates folder of each app and places it in one static folder. This is why the app name needs to be twice in the path. Because in the final folder you end up with the app names already there. Also, you could have in your app overridden templates from third party apps (e.g. admin). It sounds a bit too convoluted for me too, but I'm pretty sure that is the intended way you're supposed to separate templates.

Also, in your view, you need to have the app name when specifying the template_name option:

# simplevent app
class Landing(TemplateView):
    template_name = "simplevent/landing.html"


# nexttrain app
class Landing(TemplateView):
    template_name = "nexttrain/landing.html"

PS. the same principle is applied to static folders.

Back to Top