复写模板

在项目中,你可以想要在另一个 Django 应用中重写模板,不论它是第三方应用或 contrib 应用,例如 django.contrib.admin。你可以将重写的模板置于工程的模板目录或应用的模板目录。

若应用和工程的模板模板都包含被重写的模板,默认的 Django 模板加载器会先尝试加载工程目录下的模板。换句话说,先查找 DIRS,其次 APP_DIRS

参见

阅读 重写内置视图模板 若你正在找相关资料。

重写来自工程目录的模板

首先,我们探索用在工程模板目录创建替代模板的方法。

假设你正在重写第三方应用 blog 的模板,该应用提供了 blog/post.htmlblog/list.html 模板。工程关键配置如下:

  1. from pathlib import Path
  2. BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
  3. INSTALLED_APPS = [
  4. ...,
  5. 'blog',
  6. ...,
  7. ]
  8. TEMPLATES = [
  9. {
  10. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  11. 'DIRS': [BASE_DIR / 'templates'],
  12. 'APP_DIRS': True,
  13. ...
  14. },
  15. ]

若用模板工程模板创建工程,则 TEMPLATESBASE_DIR 早已存在。需要修改的配置是 DIRS

这些配置假定在工程根目录下有个 templates 目录。要重写 blog 应用的模板,在 templates 目录中创建一个文件夹,然后将以下模板文件添加至该目录:

  1. templates/
  2. blog/
  3. list.html
  4. post.html

模板加载器会先查找 DIRS 目录下的模板。当 blog 应用中的视图要求 blog/post.htmlblog/list.html 模板,加载器会返回你刚创建的文件。

重写来自应用模板目录的模板

由于重写的模板位于工程应用之外,更常见的做法是使用第一个方法,然后将重写的模板置于工程模板目录。然而,如果你偏爱将重写的模板放入应用模板目录,也是可以的。

首先,确保模板配置会搜索应用模板目录:

  1. TEMPLATES = [
  2. {
  3. ...,
  4. 'APP_DIRS': True,
  5. ...
  6. },
  7. ]

若你想重写名为 blog/list.htmlblog/post.html 的模板,并将它们置于名为 myapp 的应用中,那么目录结构应该看起来像这样:

  1. myapp/
  2. templates/
  3. blog/
  4. list.html
  5. post.html

APP_DIRS 置为 True 时,模板加载器会深入应用的模板目录查找模板。

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

  1. {% extends "admin/base_site.html" %}
  2. {% block branding %}
  3. <img src="link/to/logo.png" alt="logo">
  4. {{ block.super }}
  5. {% endblock %}

Key points to note:

  • The example creates a file at templates/admin/base_site.html that uses the configured project-level templates directory to override admin/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 using block.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.