Django TemplateDoesNotExist (tested)
Django raises TemplateDoesNotExist when no template loader finds the name you asked for. The exception lists every path it tried; usually the project templates/ folder is missing from DIRS, or an app template needs its app/ prefix.
Setup
A minimal project, rendered with settings.configure() so every block is runnable on its own:
proj/
blog/__init__.py
blog/templates/blog/post.html # app template, namespaced
templates/home.html # project-level template
templates/page.html # {% extends "base.html" %} (base.html missing)
common.py # sys.path.insert(0, "/w/proj"); BASE = Path("/w/proj")
1. Reproduce it: DIRS empty, app template not namespaced
from common import *
settings.configure(
INSTALLED_APPS=['blog'],
TEMPLATES=[{'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], # project templates/ not listed
'APP_DIRS': True}])
django.setup()
from django.template.loader import render_to_string
from django.template import TemplateDoesNotExist
for name in ['post.html', 'home.html', 'blog/post.html']:
try:
print(name, '->', render_to_string(name, {'n': 1}).strip())
except TemplateDoesNotExist as e:
print(name, '->', type(e).__name__ + ':', e)
for origin, status in e.chain[0].tried:
print(' tried', origin.name, '|', status)
Output:
post.html -> TemplateDoesNotExist: post.html
tried /w/proj/blog/templates/post.html | Source does not exist
home.html -> TemplateDoesNotExist: home.html
tried /w/proj/blog/templates/home.html | Source does not exist
blog/post.html -> Post 1
Three things to read from this:
- The exception's
chain[0].triedlist (the same data as the debug page's Template-loader postmortem) shows every path Django checked. If your file is not under one of those directories, Django never looked there. - With
APP_DIRS: TrueDjango searches<app>/templates/, so a file atblog/templates/blog/post.htmlis namedblog/post.html, notpost.html. The innerblog/folder is the namespace that keeps two apps'post.htmlfrom clashing. - A project-level
templates/folder is not searched at all unless it is listed inDIRS.
2. Fix: add the project folder to DIRS
from common import *
settings.configure(
INSTALLED_APPS=['blog'],
TEMPLATES=[{'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE / 'templates'], # the fix
'APP_DIRS': True}])
django.setup()
from django.template.loader import render_to_string
for name in ['home.html', 'blog/post.html']:
print(name, '->', render_to_string(name, {'n': 1}).strip())
Output:
home.html -> Home
blog/post.html -> Post 1
In a real settings.py this is 'DIRS': [BASE_DIR / 'templates']. Use an absolute path built from BASE_DIR; a relative string depends on the directory you start the server from.
3. Two other causes: app not installed, and a missing parent template
from common import *
settings.configure(
INSTALLED_APPS=[], # 'blog' forgotten
TEMPLATES=[{'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE / 'templates'], 'APP_DIRS': True}])
django.setup()
from django.template.loader import render_to_string
from django.template import TemplateDoesNotExist
for name in ['blog/post.html', 'page.html']:
try:
print(name, '->', render_to_string(name).strip())
except TemplateDoesNotExist as e:
print(name, '->', type(e).__name__ + ':', e)
Output:
blog/post.html -> TemplateDoesNotExist: blog/post.html
page.html -> TemplateDoesNotExist: base.html
App templates are only found for apps listed in INSTALLED_APPS, so a new app you forgot to add gives TemplateDoesNotExist even though the file is in the right place. And when the error names a template you never rendered directly (here base.html while rendering page.html), it comes from an {% extends %} or {% include %} inside the template: fix that path.
Checklist
- Read the postmortem /
triedlist: is your file's directory in it? - App template: is the app in
INSTALLED_APPS,APP_DIRSTrue, and is the name you passapp/file.html? - Project template: is
BASE_DIR / 'templates'inDIRS? - Spelling and case: Linux filesystems are case-sensitive.
- Error names a different template? Check
extends/includetags.
Related: Flask TemplateNotFound.
Frequently asked questions
Why does Django not find my templates folder?
A project-level templates/ folder is only searched if it is in TEMPLATES['DIRS'], e.g. BASE_DIR / 'templates'. APP_DIRS only covers <app>/templates/ of installed apps.
Why does TemplateDoesNotExist name base.html?
The template you rendered extends or includes base.html, and that file is not on any loader path.
Written with AI assistance. Measured on 2026-10-23 with Django 6.1.2 and Python 3.14.7 (python:3-alpine in Docker). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and Django are free.