Django 模板继承详解
一、什么是 Django 模板继承
Django 的模板继承机制用于构建可复用的页面结构。其核心原理是先定义一个基础模板(父模板),再通过子模板扩展或覆盖其中的内容块,从而避免重复编写相同的 HTML。
这种设计遵循 DRY 原则(Don't Repeat Yourself):既保证全站布局统一,又允许各页面定制自己的内容。模块化的管理方式让模板更易维护。
核心语法速览:
| 语法 | 作用 |
|---|---|
{% block name %}{% endblock %} |
在父模板中定义可被覆盖的"插槽" |
{% extends "base.html" %} |
子模板声明继承的父模板(必须放在第一行) |
{``{ block.super }} |
在子模板中调用父模板该块的原始内容 |
{% include "xxx.html" %} |
嵌入另一个模板片段(与继承互补) |
二、父模板
假设有一个名为 base.html 的模板,定义了网站的基本结构:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>Welcome to My Website</h1>
</header>
<main>
{% block content %}
<!-- 默认内容 -->
<p>This is the default content.</p>
{% endblock %}
</main>
<footer>
<p>© 2023 My Website</p>
</footer>
</body>
</html>
关键点:
-
{% block title %}和{% block content %}是预留的"插槽" -
块内可以写默认内容,子模板不覆盖时显示默认值
-
块名必须唯一且语义清晰(如
content、sidebar、scripts)
三、子模板
子模板通过 {% extends %} 继承父模板,并覆盖需要定制的块:
html
{% extends "base.html" %}
{% block title %}About Us - My Website{% endblock %}
{% block content %}
<h2>关于我们</h2>
<p>这是关于页面的专属内容。</p>
<ul>
<li>公司简介</li>
<li>联系方式</li>
</ul>
{% endblock %}
渲染结果:
-
HTML 骨架、页头、页脚均来自
base.html -
<title>被替换为About Us - My Website -
<main>中的默认内容被关于页面的内容完全替换
执行规则:
-
{% extends %}必须是子模板的第一个标签,否则继承无效 -
子模板只能覆盖父模板中已定义的块
-
未被覆盖的块沿用父模板的默认内容
四、进阶用法
1. 调用父模板原始内容({``{ block.super }})
当子模板需要在父模板原有内容基础上追加而非完全覆盖时:
html
{% block content %}
{{ block.super }} <!-- 保留父模板默认内容 -->
<p>这是新增的追加内容。</p>
{% endblock %}
常见场景:父模板已引入基础 CSS/JS,子模板需追加自己专属的样式或脚本。
2. 多层继承
模板可以链式继承,适合大型项目分层组织:
text
base.html → 全站骨架(header / footer / 全局样式)
└─ base_article.html → 文章模块公共结构(侧边栏 / 目录)
└─ article_detail.html → 具体文章页面
3. 多块配合
父模板通常定义多个块,方便子模板精确控制:
html
<head>
{% block meta %}{% endblock %}
{% block styles %}{% endblock %}
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
{% block header %}{% endblock %}
{% block content %}{% endblock %}
{% block footer %}{% endblock %}
{% block scripts %}{% endblock %}
</body>
4. 配合静态文件
html
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
5. 与 {% include %} 的区别
| 特性 | {% extends %} 继承 |
{% include %} 包含 |
|---|---|---|
| 用途 | 复用整体页面骨架 | 复用局部组件(导航、卡片) |
| 关系 | 父子模板,一对一 | 平级嵌入,可多次包含 |
| 覆盖 | 子模板可覆盖父块 | 无法覆盖,仅原样嵌入 |
五、最佳实践
| 实践 | 说明 |
|---|---|
{% extends %} 放第一行 |
必须是子模板第一个标签,否则继承不生效 |
| 块名语义化 | 用 content、sidebar、scripts,避免 block1 |
| 父模板不写过多业务内容 | 只保留骨架与默认占位 |
| 子模板不重复 HTML 结构 | 只覆盖需要变化的块,减少冗余 |
合理使用 block.super |
需在父内容基础上扩展时使用 |
| 目录规范化 | 建议 templates/base.html + templates/app/xxx.html |
| 适度继承层级 | 通常 2~3 层为宜,过深会降低可读性 |
六、总结
Django 模板继承通过 父模板定义骨架 + 子模板填充内容 的方式,实现了:
-
代码复用:公共结构只写一次
-
一致性:全站布局统一
-
灵活性:每个页面可定制自己的块
-
易维护:修改父模板即可影响全站
这是 Django 模板系统中最重要、最常用的机制之一,掌握它能显著提升开发效率和项目可维护性。