如何覆盖模板¶
在项目中,你可以想要在另一个 Django 应用中重写模板,不论它是第三方应用或 contrib 应用,例如 django.contrib.admin
。你可以将重写的模板置于工程的模板目录或应用的模板目录。
若应用和工程的模板模板都包含被重写的模板,默认的 Django 模板加载器会先尝试加载工程目录下的模板。换句话说,先查找 DIRS
,其次 APP_DIRS
。
参见
阅读 重写内置视图模板 若你正在找相关资料。
重写来自工程目录的模板¶
首先,我们探索用在工程模板目录创建替代模板的方法。
假设你正在重写第三方应用 blog
的模板,该应用提供了 blog/post.html
和 blog/list.html
模板。工程关键配置如下:
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,
# ...
},
]
若用模板工程模板创建工程,则 TEMPLATES
和 BASE_DIR
早已存在。需要修改的配置是 DIRS
。
这些配置假定在工程根目录下有个 templates
目录。要重写 blog
应用的模板,在 templates
目录中创建一个文件夹,然后将以下模板文件添加至该目录:
templates/
blog/
list.html
post.html
模板加载器会先查找 DIRS
目录下的模板。当 blog
应用中的视图要求 blog/post.html
和 blog/list.html
模板,加载器会返回你刚创建的文件。
重写来自应用模板目录的模板¶
由于重写的模板位于工程应用之外,更常见的做法是使用第一个方法,然后将重写的模板置于工程模板目录。然而,如果你偏爱将重写的模板放入应用模板目录,也是可以的。
首先,确保模板配置会搜索应用模板目录:
TEMPLATES = [
{
# ...
"APP_DIRS": True,
# ...
},
]
若你想重写名为 blog/list.html
和 blog/post.html
的模板,并将它们置于名为 myapp
的应用中,那么目录结构应该看起来像这样:
myapp/
templates/
blog/
list.html
post.html
当 APP_DIRS
置为 True
时,模板加载器会深入应用的模板目录查找模板。
扩展复写模板¶
当你配置好你的模板加载器后,你可以使用 {% extends %}
模板标签的同时来覆盖它。这样可以让你不用重写整个模板就可以做一些微小的改动。
举个例子,你可以使用这项技术在 admin/base_site.html
管理员模板中添加自定义的Logo:
{% extends "admin/base_site.html" %} {% block branding %} <img src="link/to/logo.png" alt="logo"> {{ block.super }} {% endblock %}
关键注意点:
- 这个例子创建了使用配置好的项目级
templates
目录创建了管理员文件templates/admin/base_site.html
来覆盖管理员文件admin/base_site.html
。 - 新的管理员模板拓展了
admin/base_site.html
并覆盖了它。 - 新模板只是替换了
branding
区域,添加了一个自定义的Logo,和使用了block.super
以继承原有的内容。 - 被继承的管理员模板
admin/base_site.html
的其他内容没有变化。
这个技术起作用是因为当解析到 extends
标签时模板加载器不认为这是已经加载过的有覆盖的模板(管理员模板位于 templates/admin/base_site.html
)。与 block.super
的结合是对原有内容做很小的改动的有力技术。