2025, Sep 26 11:00
Resolve Django LoginView TemplateDoesNotExist for registration/login.html with APP_DIRS and template_name
Learn how to fix Django's TemplateDoesNotExist for registration/login.html by enabling APP_DIRS and setting LoginView's template_name. Covers URLconf changes.
Hitting /accounts/login/ and getting TemplateDoesNotExist for registration/login.html is a classic gotcha when wiring Django’s built-in auth views. You finish the setup, run the server, open the login URL, and Django complains that it can’t find the template. The error shows the template loader searching known locations but not seeing your app’s template, which is exactly where LoginView expects it by default.
What the failing setup looks like
The URLconf wires the built-in views without explicitly telling Django which template to use. That’s perfectly fine as long as the conventional template is discoverable on the template search path.
from django.contrib import admin
from django.contrib.auth import views as auth_screens
from django.urls import path
urlpatterns = [
  path("accounts/login/", auth_screens.LoginView.as_view(), name="login"),
  path("accounts/logout/", auth_screens.LogoutView.as_view(), name="logout"),
  path("admin/", admin.site.urls),
]
The template engine is configured to use the app directories loader. That means Django will look for a templates folder inside each installed app and collect templates from there.
TEMPLATES = [
  {
    "BACKEND": "django.template.backends.django.DjangoTemplates",
    "DIRS": [],
    "APP_DIRS": True,
    "OPTIONS": {
      "context_processors": [
        "django.template.context_processors.request",
        "django.contrib.auth.context_processors.auth",
        "django.contrib.messages.context_processors.messages",
      ],
    },
  },
]
Why the error happens
Django’s LoginView expects a template at registration/login.html. With APP_DIRS enabled, the app_directories loader will scan all installed apps for a templates directory and try to resolve that relative path. If the file is not present in any discovered templates directory, or Django doesn’t point to your file explicitly, the loader raises TemplateDoesNotExist. The postmortem shows Django checking known template locations and not finding registration/login.html where it expects it.
The fix
There are two moving parts, and both need to align. First, the template engine must actually look into your app templates, so APP_DIRS must be True. Second, either place the file under the conventional path in your app or tell LoginView exactly which template to render.
Ensure the template engine is configured like this:
TEMPLATES = [{
  "BACKEND": "django.template.backends.django.DjangoTemplates",
  "DIRS": [],
  "APP_DIRS": True,
  "OPTIONS": {"context_processors": [
    "django.template.context_processors.request",
    "django.contrib.auth.context_processors.auth",
    "django.contrib.messages.context_processors.messages",
  ]},
}]
Place the login template at the conventional location inside your app:
courses/templates/registration/login.html
And make the URLconf explicit, so the view resolves that file regardless of where else Django looks:
from django.contrib import admin
from django.contrib.auth import views as auth_screens
from django.urls import path
urlpatterns = [
  path(
    "accounts/login/",
    auth_screens.LoginView.as_view(template_name="registration/login.html"),
    name="login",
  ),
  path("accounts/logout/", auth_screens.LogoutView.as_view(), name="logout"),
  path("admin/", admin.site.urls),
]
Why this matters
Built-in auth views rely on predictable template names. If your project’s template search path or file layout drifts from those conventions, you get a TemplateDoesNotExist at runtime. Being explicit about template_name eliminates guesswork and makes your intent clear. Keeping APP_DIRS enabled ensures each installed app can ship its own templates without extra wiring.
Takeaways
When wiring Django auth screens, think in terms of two contracts: where the view looks by default and where your template actually lives. Put registration/login.html under the app’s templates directory, keep APP_DIRS set to True, and override template_name on the view when you want to be crystal clear. This saves time and avoids the “works on my machine” chase later.
The article is based on a question from StackOverflow by Jason Sturgeon and an answer by Umar Sherwani.