Django笔记&教程 3-4 模板继承
阅读原文时间:2022年04月07日阅读:1

Django 自学笔记兼学习教程第3章第4节——模板继承

点击查看教程总目录

在介绍具体的技术之前,先介绍在什么样的场景中,需要使用这样的技术,我觉得这对于新手理解起来很重要。

一般来说,要渲染一个页面我们就需要新建一个对应的模板,然而一个系统中,多个页面常常会有很多功能相似的内容区域,比如都有头部栏、侧边栏、底部信息栏等等,这样的内容区域是多个页面共有的,如果我们不思考采用新的技术方式,而是把在每个页面都写一遍这种共有内容的代码,不仅是代码重复的问题,而且会导致管理的混乱,比如要修改或者检查等等。

这里我们可以先想想python中是如何解决这个问题的,python代码会将公共使用的代码或者方法写在一个库(常常是一个py文件中),哪些py需要用到这部分内容则“导入”这部分内容。

html模板技术也是在解决这一问题,不过使用的是另一种思路,它会将共有的内容代码做成母版,那些要用到这个代码的则是子版,需要先继承母版,再编写子版对应的功能代码。这一点有点像幻灯片。

本文主要参考文档: template-inheritance

1 模板继承介绍

官方介绍如下:

模板继承是Django模板引擎中功能最强大的部分,也是最复杂的部分。

模板继承允许你构建一个基本的“骨架”模板,它包含你网站的所有公共元素,并定义子模板可以覆盖的块(即子模板可以自定义编辑的区域)。

2 “母版”

这里用我之前的代码(本章第一节展示过的)作为示例来讲解下模板继承

首先是background.html

<!DOCTYPE html>
<html lang="en">
<head>

    <title>
        学生选课管理系统
    </title>
</head>
<body>
<div class="main-container">
    <div class="main-header">
        <div class="main-title">学生选课管理系统</div>
        <div class="sub-title">Student Course Management System</div>
        {% block welcome_message %}
        {% endblock %}
    </div>
    <div class="login-container">
        {% block login_container %}
        {% endblock %}
    </div>
</div>
</body>
</html>

这个就是我们的母版。

官方文档一般称其为html骨架文档,习惯用base.html来命名,“子”模板的工作就是用内容填充骨架中的空块。

那么哪些是子模板可以填充的空块呢?

我们观察下上面和普通html语法格格不入的代码块,有两块:

{% block welcome_message %}
{% endblock %}


{% block login_container %}
{% endblock %}

这两块就是子模板可以进行填充的,即子模板可以自定义内容的。

其中block是块标记,所做的只是告诉模板引擎子模板可以覆盖模板的那些部分。

block后面接的一串字符串是这个块的名字,可以认为是一个辨识用的id,后面子模板会用这个id去标明自己要覆盖哪个。

endblock则是一个没有具体意义的结束符,用于标明block这个块到这里为止。

3 继承“母版”

母版初步介绍完了,接下来我们看看子版login_home.html

{% extends "user/background.html" %}
{% block login_container %}
<div class="login-kind student-login-button">
    <a href="">学生登录</a>
</div>
<div class="login-kind teacher-login-button">
    <a href="">教师登录</a>
</div>
{% endblock %}

其中第一行的extends标签是关键:它告诉模板引擎,这个模板“继承”另一个模板。

注:extends必须在第一行写。

当模板系统计算这个模板时,它首先定位父模板——在本例中是background.html

然后,模板引擎将注意到background.html中的两个block块标记,并用子模板的对应block快内容替换这些块。

上面的例子中,login_home.html的值,输出可能如下所示:

<!DOCTYPE html>
<html lang="en">
<head>

    <title>
        学生选课管理系统
    </title>
</head>
<body>
<div class="main-container">
    <div class="main-header">
        <div class="main-title">学生选课管理系统</div>
        <div class="sub-title">Student Course Management System</div>
    </div>
    <div class="login-container">
        <div class="login-kind student-login-button">
            <a href="">学生登录</a>
        </div>
        <div class="login-kind teacher-login-button">
            <a href="">教师登录</a>
        </div>
    </div>
</div>
</body>
</html>

注意,由于子模板没有定义welcome_message 块,所以使用了父模板的值(在上面的例子中是一个空值)。父模板中{% block %}标记内的内容总是用作这样一种场景里的回退。

同时,在子模板中,也可以添加新的block块给下一级子模板使用,即子模板本身也可以作为一个母版。

实际中,可以根据需要使用任意多层的继承级别。