How can I resolve this Django TemplateDoesNotExist error?
I'm working through the "Django 5 by Example" textbook, and am nearly finished with chapter 12, however at the very end when the text asks you to runserver and checkout http://127.0.0.1:8000/accounts/login, I get the following error:
TemplateDoesNotExist at /accounts/login/ registration/login.html Request Method: GET Request URL: http://127.0.0.1:8000/accounts/login/ Django Version: 5.2.5 Exception Type: TemplateDoesNotExist Exception Value: registration/login.html Exception Location: C:\Users\Zergy\python\django\django-learning\env\educa\Lib\site-packages\django\template\loader.py, line 47, in select_template Raised during: django.contrib.auth.views.LoginView Python Executable: C:\Users\Zergy\python\django\django-learning\env\educa\Scripts\python.exe Python Version: 3.13.1 Python Path: ['C:\Users\Zergy\python\django\django-learning\educa', 'C:\Users\Zergy\AppData\Local\Programs\Python\Python313\python313.zip', 'C:\Users\Zergy\AppData\Local\Programs\Python\Python313\DLLs', 'C:\Users\Zergy\AppData\Local\Programs\Python\Python313\Lib', 'C:\Users\Zergy\AppData\Local\Programs\Python\Python313', 'C:\Users\Zergy\python\django\django-learning\env\educa', 'C:\Users\Zergy\python\django\django-learning\env\educa\Lib\site-packages']
Template-loader postmortem Django tried loading these templates, in this order:
Using engine django:
django.template.loaders.app_directories.Loader: C:\Users\Zergy\python\django\django-learning\env\educa\Lib\site-packages\django\contrib\admin\templates\registration\login.html (Source does not exist) django.template.loaders.app_directories.Loader: C:\Users\Zergy\python\django\django-learning\env\educa\Lib\site-packages\django\contrib\auth\templates\registration\login.html (Source does not exist)
I have checked, double-checked and triple-checked that my spelling and file structure are the same as what is given in the textbook, but the error persists.
Here's the relevant parts of settings.py:
INSTALLED_APPS = [
'courses.apps.CoursesConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
ROOT_URLCONF = 'educa.urls'
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',
],
},
},
]
Here is the file structure
Here is educa/urls.py
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('accounts/login/', auth_views.LoginView.as_view(), name='login'),
path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
path('admin/', admin.site.urls),
]
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
)
Here is courses/templates/base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{% block title %}Educa{% endblock title %}</title>
<link rel="stylesheet" href="{% static "css/base.css" %}">
</head>
<body>
<div id="header">
<a href="/" class="logo">Educa</a>
<ul class="menu">
{% if request.user.is_authenticated %}
<li>
<form action="{% url "logout" %}" method="post">
<button type="submit">Sign out</button>
</form>
</li>
{% else %}
<li><a href="{% url "login" %}">Sign in</a></li>
{% endif %}
</ul>
</div>
<div id="content">
{% block content %}
{% endblock content %}
</div>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
// DOM DOMContentLoaded
{% block domready %}
{% endblock %}
})
</script>
</body>
</html>
here is courses/templates/registration/login.html
{% extends "base.html" %}
{% block title %}Log-in{% endblock title %}
{% block content %}
<h1>Log-in</h1>
<div class="module">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% else %}
<p>Please, use the following form to log-in:</p>
{% endif %}
<div class="login-form">
<form action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}" />
<p><input type="submit" value="Log-in"></p>
</form>
</div>
</div>
{% endblock content %}
finally here is courses/admin.py (if needed)
from django.contrib import admin
from .models import Subject, Course, Module
@admin.register(Subject)
class SubjectAdmin(admin.ModelAdmin):
list_display = ['title', 'slug']
prepopulated_fields = {'slug': ('title',)}
class ModuleInline(admin.StackedInline):
model = Module
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ['title', 'subject', 'created']
list_filter = ['created', 'subject']
search_fields = ['title', 'overview']
prepopulated_fields = {'slug': ('title',)}
inlines = [ModuleInline]
I have checked a number of old stackoverflow posts regarding this error, but none of the solutions I have seen (such as adding a / at the end of the url route) were relevant to my situation. I have done all I can apart from literally copy pasting the entire repository here to make my project look like the textbook, but I still get this error. My intuition tells me that the folder structure is somehow wrong, but if so, why does the textbook show it like this? Is it outdated?
TEMPLATES = [{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True, # <-- must be 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
path("accounts/login/",
auth_views.LoginView.as_view(template_name="registration/login.html"),
name="login")