2025, Sep 26 11:16

TemplateDoesNotExist для registration/login.html в Django: быстрый фикс

Ошибка TemplateDoesNotExist в Django LoginView? Разберём, почему не находится registration/login.html, как настроить APP_DIRS и явно указать template_name.

Переходите на /accounts/login/ — и в ответ TemplateDoesNotExist для registration/login.html. Это типичная ловушка при подключении встроенных экранов аутентификации Django. Кажется, всё настроено: запускаете сервер, открываете URL входа, а Django жалуется, что не может найти шаблон. В трассировке видно, как загрузчик перебирает стандартные места, но не видит шаблон вашего приложения — ровно там, где LoginView по умолчанию его ожидает.

Как выглядит неудачная настройка

В URLconf подключены встроенные представления без явного указания, какой шаблон использовать. Это работает, пока шаблон с ожидаемым именем доступен в путях поиска шаблонов.

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),
]

Движок шаблонов настроен на использование загрузчика каталогов приложений. Это означает, что Django будет искать папку templates внутри каждого установленного приложения и забирать оттуда шаблоны.

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",
      ],
    },
  },
]

Почему возникает ошибка

LoginView в Django ожидает шаблон по пути registration/login.html. При включённом APP_DIRS загрузчик app_directories просканирует все установленные приложения в поисках каталога templates и попытается разрешить этот относительный путь. Если файл не найден ни в одном из обнаруженных каталогов шаблонов, либо Django не указывает на ваш файл явно, загрузчик выбросит TemplateDoesNotExist. В отчёте видно, что Django проверяет известные места и не находит registration/login.html там, где рассчитывает.

Как исправить

Есть две составляющие, и обе должны совпасть. Во‑первых, движок шаблонов действительно должен смотреть в шаблоны вашего приложения, поэтому APP_DIRS должен быть True. Во‑вторых, либо положите файл по принятому пути внутри приложения, либо явно укажите LoginView, какой шаблон рендерить.

Убедитесь, что движок шаблонов настроен так:

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",
  ]},
}]

Разместите шаблон входа в принятом месте внутри вашего приложения:

courses/templates/registration/login.html

И сделайте явную привязку в URLconf, чтобы представление находило этот файл независимо от того, где ещё ищет Django:

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),
]

Почему это важно

Встроенные представления аутентификации опираются на предсказуемые имена шаблонов. Если пути поиска шаблонов или структура файлов в проекте расходятся с этими соглашениями, во время выполнения вы получите TemplateDoesNotExist. Явное указание template_name снимает двусмысленность и делает намерение прозрачным. Включённый APP_DIRS гарантирует, что каждое установленное приложение может поставлять собственные шаблоны без дополнительной проводки.

Выводы

Подключая экраны аутентификации Django, держите в голове два условия: где представление ищет шаблон по умолчанию и где на самом деле лежит ваш файл. Поместите registration/login.html в каталог templates вашего приложения, оставьте APP_DIRS равным True и переопределяйте template_name у представления, когда нужно полной ясности. Это экономит время и избавляет от погони за «у меня работает» позже.

Статья основана на вопросе на StackOverflow от Jason Sturgeon и ответе от Umar Sherwani.