Jinja2 宏与高级模板
1. 宏(Macros)
定义宏:
{% macro 宏名称(参数) %}
代码块
{% endmacro %}
{# 示例 #}
{% macro input(label, name, type='text') %}
<label>{{ label }}</label>
<input type="{{ type }}" name="{{ name }}">
{% endmacro %}
调用宏:
{{ input('用户名', 'username') }}
{{ input('密码', 'password', 'password') }}
导入宏:
{# 整体导入 #}
{% import 'macro.html' as my_input %}
{{ my_input.input('邮箱', 'email') }}
{# 选择性导入 #}
{% from 'macro.html' import input %}
{{ input('提交', 'submit', 'submit') }}
{# 带别名导入 #}
{% from 'macro.html' import input as input_field %}
{{ input_field('搜索', 'search') }}
2. 模板继承
父模板 (base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<h1>这里是头部</h1>
<br />
{% block body %}
这里预留给子模板填充
{% endblock body %}
<br />
<h2>这里是底部内容</h2>
</body>
</html>
子模板继承:
{% extends 'base.html' %}
{% block title %}子页面标题{% endblock %}
{% block body %}
<h6>子模板填充的内容</h6>
{{ super() }} {# 调用父模板内容 #}
<p>新增内容区域</p>
{% endblock body %}
3. 包含(Include)
{# 基础包含 #}
{% include 'header.html' %}
{# 安全包含(忽略缺失文件) #}
{% include 'sidebar.html' ignore missing %}
<main>
{# 主要内容区 #}
{% block content %}{% endblock %}
</main>
{% include 'footer.html' %}
4. 宏、继承、包含对比
| 特性 | 宏 (Macro) | 继承 (Extends) | 包含 (Include) |
|---|---|---|---|
| 本质 | 函数式代码复用 | 父模板框架+子模板填充 | 直接嵌入外部模板内容 |
| 参数支持 | 支持参数传递 | 通过 block 传递内容 | 无参数 |
| 作用域 | 独立作用域 | 继承父模板完整环境 | 共享当前模板环境 |
| 错误处理 | 宏内错误局部化 | 继承链错误全局影响 | 文件缺失可忽略 |
| 适用场景 | 表单元素/UI组件/重复代码片段 | 网站基础布局/页面框架 | 公共片段(页头/页脚/广告位) |
| 代码组织 | 单独宏文件 | 父子模板层级结构 | 分散模板文件 |
5. 特殊模板变量
| 变量/方法 | 说明 | 使用示例 |
|---|---|---|
config | Flask 配置对象 | {{ config.SECRET_KEY }} |
request | 当前请求对象 | {{ request.method }} |
session | 用户会话对象 | {{ session.user_id }} |
url_for() | URL 反向解析 | {{ url_for('user_profile', id=123) }} |
get_flashed_messages() | 获取 flash 消息队列 | 见下方详细示例 |
get_flashed_messages 使用:
# 视图函数 (app.py)
from flask import Flask, render_template, flash
app = Flask(__name__)
@app.route('/')
def index():
flash('Python消息')
flash('Flask消息')
flash('Django消息')
return render_template('messages.html')
{# 模板文件 (messages.html) #}
{% for message in get_flashed_messages() %}
<div class="alert">{{ message }}</div>
{% endfor %}
{# 输出:
<div class="alert">Python消息</div>
<div class="alert">Flask消息</div>
<div class="alert">Django消息</div>
#}
6. 高级技巧
1. 多层继承:
{# 三级继承示例 #}
base.html → layout.html → page.html
{# page.html #}
{% extends "layout.html" %}
{# layout.html #}
{% extends "base.html" %}
{% block content %}
<section>{% block section %}{% endblock %}</section>
{% endblock %}
2. 宏嵌套:
{% macro form_field(field) %}
<div class="form-group">
{{ field.label }}
{{ field() }}
{% if field.errors %}
<span class="error">{{ field.errors[0] }}</span>
{% endif %}
</div>
{% endmacro %}
{% macro render_form(form) %}
<form method="post">
{{ form.csrf_token }}
{% for field in form %}
{{ form_field(field) }}
{% endfor %}
<button type="submit">提交</button>
</form>
{% endmacro %}
3. 动态包含:
{% set template_name = 'widgets/' + widget_type + '.html' %}
{% include template_name ignore missing %}
4. 块控制:
{# 禁止块覆盖 #}
{% block footer %}{% endblock %} {# 空块防止子模板覆盖 #}
{# 块追加内容 #}
{% block scripts %}
{{ super() }}
<script src="/custom.js"></script>
{% endblock %}
5. 特殊块类型:
{% block head %}
{{ super() }} {# 保留父模板head内容 #}
<style>
/* 页面专用样式 */
</style>
{% endblock %}
{% block javascript %}
<script>
// 页面专用脚本
</script>
{% endblock %}
所有内容已完整保留原始文档结构,修正了示例中的拼写错误(如
render_templates→render_template),确保语法符合 Jinja2 3.x 规范,可直接用于 Flask 项目开发。
掌握Jinja2宏与模板高级技巧
1172

被折叠的 条评论
为什么被折叠?



