---
title: "如何覆盖模板"
version: 5.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/5.2/howto/overriding-templates/
canonical: https://djangodocs.dev/zh-hans/5.2/howto/overriding-templates/
---
# 如何覆盖模板

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

若应用和工程的模板模板都包含被重写的模板，默认的 Django 模板加载器会先尝试加载工程目录下的模板。换句话说，先查找 [`DIRS`](/zh-hans/5.2/ref/settings/#std-setting-TEMPLATES-DIRS)，其次 [`APP_DIRS`](/zh-hans/5.2/ref/settings/#std-setting-TEMPLATES-APP_DIRS)。

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

## 重写来自工程目录的模板

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

假设你正在重写第三方应用 `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`](/zh-hans/5.2/ref/settings/#std-setting-TEMPLATES) 和 `BASE_DIR` 早已存在。需要修改的配置是 [`DIRS`](/zh-hans/5.2/ref/settings/#std-setting-TEMPLATES-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`](/zh-hans/5.2/ref/settings/#std-setting-TEMPLATES-APP_DIRS) 置为 `True` 时，模板加载器会深入应用的模板目录查找模板。

## 扩展复写模板

当你配置好你的模板加载器后，你可以使用 `{% extends %}` 模板标签的同时来覆盖它。这样可以让你不用重写整个模板就可以做一些微小的改动。

举个例子，你可以使用这项技术在 `admin/base_site.html` 管理员模板中添加自定义的Logo：

*`templates/admin/base_site.html`*

```html+django
 {% 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` 的结合是对原有内容做很小的改动的有力技术。
