使用模板继承组织模板

对于模板内容重复的问题,Jinja2 提供了模板继承的支持。
这个机制和 Python 类 继承非常类似:
我们可以定义一个父模板,一般会称之为基模板(base template)。
基模板中包含完整的 HTML 结构和导航栏、页首、页脚都通用部分。
在子模板里,我们可以使用 extends 标签来声明继承自某个基模板。
基模板中需要在实际的子模板中追加或重写的部分则可以定义成块(block)。
块使用block 标签创建, {% block 块名称 %} 作为开始标记
{% endblock %} 或 {% endblock 块名称 %} 作为结束标记。
通过在子模板里定义一个同样名称的块,你可以向基模板的对应块位置追加或重写内容。

编写基础模板

  • 下面是新编写的基模板 base.html: templates/base.html:基模板
<!DOCTYPE html> 
<html lang="en"> 
<head>
    {% block head %}
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-s cale=1.0">
    <title>{{ user.name }}'s Watchlist</title>
    <link rel="icon" href="{{ url_for('static', filename='favico n.ico') }}">
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
    {% endblock %}
</head> 
<body>
    <h2>
        <img alt="Avatar" class="avatar" src="{{ url_for('static', filename='images/avatar.png') }}">
        {{ user.name }}'s Watchlist
    </h2>
    <nav>
        <ul>
            <li><a href="{{ url_for('index') }}">Home</a></li>
        </ul>
    </nav>
    {% block content %}{% endblock %}
    <footer>
        <small>© 2018 <a href="https://5yang.cc">HelloFlask</a></small>
    </footer>
</body>
</html>

在基模板里,我们添加了两个块,一个是包含

内容的 head 块,另一个是用来在子模板中插入页面主体内容的 content 块。在复杂的项目 里,你可以定义更多的块,方便在子模板中对基模板的各个部分插入内容。另外,块的名字没有特定要求,你可以自由修改。
* 在编写子模板之前,我们先来看一下基模板中的两处新变化。
第一处,我们添加了一个新的 元素,这个元素会设置页面的视口,让页 面根据设备的宽度来自动缩放页面,让移动设备拥有更好的浏览体验:

<meta name="viewport" content="width=device-width, initial-scale =1.0">

第二处,新的页面添加了一个导航栏:

<nav><ul><li><a href="{{ url_for('index') }}">Home</a></li> </ul> </nav>
  • 导航栏对应的 CSS 代码如下所示:
nav ul { 
list-style-type: none; 
margin: 0; 
padding: 0; 
overflow: hidden; 
background-color: #333; 
}
nav li { 
float: left; 
}
nav li a { 
display: block; 
color: white; 
text-align: center; 
padding: 8px 12px; 
text-decoration: none; 
}
nav li a:hover { 
background-color: #111; 
}

编写子模板

创建了基模板后,子模板的编写会变得非常简单。
* 下面是新的主页模板 (index.html): templates/index.html:继承基模板的主页模板

{% extends 'base.html' %}
{% block content %}
<p>{{ movies|length }} Titles</p>
<ul class="movie-list">
    {% for movie in movies %}
    <li>{{ movie.title }} - {{ movie.year }}
        <span class="float-right">
            <a class="imdb" href="https://www.imdb.com/find?q={{ movie.title }}" target="_blank" title="Find this movie on IMDb" rel="noopener"> IMDb</a>
        </span>
    </li>
    {% endfor %}
</ul>
<img alt="Walking Totoro" class="totoro" src="{{ url_for('static', filename='images/totoro.gif') }}" title="to~to~ro~">
{% endblock %}

第一行使用 extends 标签声明扩展自模板 base.html,可以理解成“这个模板继承 自 base.html“。接着我们定义了 content 块,这里的内容会插入到基模板中 content 块的位置。
* 提示 默认的块重写行为是覆盖,如果你想向父块里追加内容,可以在子块中使 用 super() 声明,即 {{ super() }} 。

404错误页面模板

404 错误页面的模板类似,如下所示:
* templates/404.html:继承基模板的 404 错误页面模板

{%  extends 'base.html' %}
{% block content %}
<ul class="movie-list"> 
<li>
    Page Not Found - 404 
    <span class="float-right"> 
        <a href="{{ url_for('index') }}">Go Back</a> 
    </span> 
</li> 
</ul>
{% endblock %}

添加 IMDb 链接

在主页模板里,我们还为每一个电影条目右侧添加了一个 IMDb 链接,这个链接的 href 属性的值为 IMDb 搜索页面的 URL,搜索关键词通过查询参数 q 传入,这里传入了电影的标题。 对应的 CSS 定义如下所示:

.float-right { 
float: right; 
}
.imdb { 
font-size: 12px; 
font-weight: bold; 
color: black; 
text-decoration: none; 
background: #F5C518;
border-radius: 5px; 
padding: 3px 5px; 
}

现在,我们的程序主页如下所示:
无标题.png

最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏