Python 现代开发学习笔记

(八)继承、包含与宏的组合过程

多个页面共用页头和主体位置,外层页面留一个 block,子页面填入内容。先从一个小页面观察三种组合。

<!-- 项目文件:demos/templates/demo_base.html -->
<!doctype html>
<html lang="zh-CN"><meta charset="utf-8">
<title>{% block title %}阅读书架{% endblock %}</title>
<header>我的阅读记录</header>
<main>{% block content %}{% endblock %}</main>
</html>

block title 和 block content 分别留下标题与正文的位置。子页面使用 extends 指定这份骨架:

<!-- 项目文件:demos/templates/demo_panel.html -->
{% extends 'demo_base.html' %}
{% from '_demo_macros.html' import reading_status %}
{% block title %}{{ book.title }}{% endblock %}
{% block content %}
  {% include '_demo_item.html' %}
  {{ reading_status(book.finished) }}
{% endblock %}

include 把另一份模板放在当前位置,并可读取当前位置的数据;from ... import 引入模板宏。下面两份短模板分别生成书名和状态。

<!-- 项目文件:demos/templates/_demo_item.html -->
<!-- include 直接读取调用位置的 book 变量。 -->
<h1>{{ book.title }}</h1>
<!-- 项目文件:demos/templates/_demo_macros.html -->
{% macro reading_status(finished) -%}
  <span>{{ '已读' if finished else '未读' }}</span>
{%- endmacro %}

宏 reading_status(finished) 像带参数的函数,接收布尔值并生成标记。'已读' if finished else '未读' 沿用条件表达式的读法;-%} 和 {%- 去掉控制语句旁多余的空白,改变排版空白,不改变判断逻辑。

# 项目文件:demos/inheritance_demo.py
from flask import Flask, render_template

app = Flask(__name__)


@app.get("/")
def index():
    # 数据仍来自已经会写的普通字典,先观察模板怎样组合。
    return render_template(
        "demo_panel.html", book={"title": "Python Web", "finished": False}
    )


if __name__ == "__main__":
    page = app.test_client().get("/")
    print(page.status_code, "Python Web" in page.text, "未读" in page.text)

执行 uv run python ../demos/inheritance_demo.py,输出 200 True True。这次渲染先取得骨架,替换标题与主体,在主体中包含书名,再调用状态宏生成“未读”。完整书架也会用同样方式组合导航、消息、表单和列表。

子模板替换父模板中的 title 和 content,再在 content 中包含书名片段并调用状态宏,最后合成一份 HTML

笔记正文与全部题解 · Ctrl / ⌘ K