How to override templates
In your project, you might want to override a template in another Django application, whether it be a third-party application or a contrib application such as django.contrib.admin
. You can either put template overrides in your project’s templates directory or in an application’s templates directory.
If you have app and project templates directories that both contain overrides, the default Django template loader will try to load the template from the project-level directory first. In other words, DIRS is searched before APP_DIRS.
See also
Read Overriding built-in widget templates if you’re looking to do that.
Overriding from the project’s templates directory
First, we’ll explore overriding templates by creating replacement templates in your project’s templates directory.
Let’s say you’re trying to override the templates for a third-party application called blog
, which provides the templates blog/post.html
and blog/list.html
. The relevant settings for your project would look like:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
INSTALLED_APPS = [
...,
"blog",
...,
]
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
# ...
},
]
The TEMPLATES setting and BASE_DIR
will already exist if you created your project using the default project template. The setting that needs to be modified is DIRS.
These settings assume you have a templates
directory in the root of your project. To override the templates for the blog
app, create a folder in the templates
directory, and add the template files to that folder:
templates/
blog/
list.html
post.html
The template loader first looks for templates in the DIRS
directory. When the views in the blog
app ask for the blog/post.html
and blog/list.html
templates, the loader will return the files you just created.
Overriding from an app’s template directory
Since you’re overriding templates located outside of one of your project’s apps, it’s more common to use the first method and put template overrides in a project’s templates folder. If you prefer, however, it’s also possible to put the overrides in an app’s template directory.
First, make sure your template settings are checking inside app directories:
TEMPLATES = [
{
# ...
"APP_DIRS": True,
# ...
},
]
If you want to put the template overrides in an app called myapp
and the templates to override are named blog/list.html
and blog/post.html
, then your directory structure will look like:
myapp/
templates/
blog/
list.html
post.html
With APP_DIRS set to True
, the template loader will look in the app’s templates directory and find the templates.
Extending an overridden template
With your template loaders configured, you can extend a template using the {% extends %} template tag whilst at the same time overriding it. This can allow you to make small customizations without needing to reimplement the entire template.
For example, you can use this technique to add a custom logo to the admin/base_site.html
template:
templates/admin/base_site.html
{% extends "admin/base_site.html" %}
{% block branding %}
<img src="link/to/logo.png" alt="logo">
{{ block.super }}
{% endblock %}
Key points to note:
- The example creates a file at
templates/admin/base_site.html
that uses the configured project-leveltemplates
directory to overrideadmin/base_site.html
. - The new template extends
admin/base_site.html
, which is the same template as is being overridden. - The template replaces just the
branding
block, adding a custom logo, and usingblock.super
to retain the prior content. - The rest of the template is inherited unchanged from
admin/base_site.html
.
This technique works because the template loader does not consider the already loaded override template (at templates/admin/base_site.html
) when resolving the extends
tag. Combined with block.super
it is a powerful technique to make small customizations.