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:

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

  1. Read the postmortem / tried list: is your file's directory in it?
  2. App template: is the app in INSTALLED_APPS, APP_DIRS True, and is the name you pass app/file.html?
  3. Project template: is BASE_DIR / 'templates' in DIRS?
  4. Spelling and case: Linux filesystems are case-sensitive.
  5. Error names a different template? Check extends/include tags.

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.