如何覆盖模板¶
在您的项目中,您可能希望覆盖另一个 Django 应用程序中的模板,无论是第三方应用程序还是诸如django.contrib.admin
之类的 contrib 应用程序。您可以将模板覆盖放在项目的模板目录或应用程序的模板目录中。
如果您有同时包含覆盖的应用程序和项目模板目录,默认的 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,
# ...
},
]
如果您想将模板覆盖放在名为myapp
的应用程序中,并且要覆盖的模板名为blog/list.html
和blog/post.html
,则您的目录结构将如下所示
myapp/
templates/
blog/
list.html
post.html
将APP_DIRS
设置为True
后,模板加载器将在应用程序的模板目录中查找并找到模板。
扩展被覆盖的模板¶
配置好模板加载器后,您可以使用{% extends %}
模板标签扩展模板,同时覆盖它。这可以让您进行小的自定义,而无需重新实现整个模板。
例如,您可以使用此技术将自定义徽标添加到admin/base_site.html
模板
templates/admin/base_site.html
¶ {% extends "admin/base_site.html" %}
{% block branding %}
<img src="link/to/logo.png" alt="logo">
{{ block.super }}
{% endblock %}
需要注意的关键点
此示例在
templates/admin/base_site.html
处创建一个文件,该文件使用配置的项目级templates
目录覆盖admin/base_site.html
。新模板扩展了
admin/base_site.html
,它与正在被覆盖的模板相同。该模板只替换了
branding
块,添加了自定义徽标,并使用block.super
保留了之前的內容。其余模板从
admin/base_site.html
继承而未更改。
此技术有效是因为模板加载器在解析extends
标签时不考虑已加载的覆盖模板(位于templates/admin/base_site.html
)。结合block.super
,它是一种进行小规模自定义的强大技术。