#Jinja2 模板引擎(上):变量渲染、循环与条件判断
📂 所属阶段:第一阶段 — 破冰启航(基础篇)
🔗 相关章节:路由(Routing)艺术 · Jinja2 模板引擎(下)
#1. Jinja2 是什么?
Jinja2 是 Flask 内置的模板引擎,使用 {{ }} 输出变量、{% %} 执行逻辑。
# Flask 自动在 templates/ 目录查找模板
from flask import render_template
@app.route("/")
def index():
return render_template("index.html", title="首页", user={"name": "Alice"})#2. 基础变量渲染
#2.1 简单变量
<!-- templates/index.html -->
<h1>{{ title }}</h1>
<p>{{ user.name }}</p>
<p>{{ user["email"] }}</p>#2.2 过滤器(Filters)
<p>大写:{{ name|upper }}</p>
<p>小写:{{ name|lower }}</p>
<p>首字母大写:{{ name|capitalize }}</p>
<p>默认值:{{ user.bio|default("暂无简介") }}</p>
<p>链式过滤:{{ name|upper|trim }}</p>
<p>安全 HTML(慎用!):{{ html_content|safe }}</p>
<p>字符串长度:{{ text|length }}</p>
<p>默认值(判断 None):{{ value|default("无") }}</p>
<p>数字格式化:{{ price|round(2) }}</p>#2.3 内置过滤器速查
| 过滤器 | 说明 | 示例 |
|---|---|---|
upper/lower | 大写/小写 | `"hello" |
capitalize | 首字母大写 | `"hello" |
trim | 去除首尾空白 | `" hi " |
length | 长度 | `"hello" |
default(value) | 默认值 | `None |
safe | 标记为安全 HTML | 仅用于可信内容 |
striptags | 去除 HTML 标签 | `"hi" |
join(val) | 连接列表 | `[1,2,3] |
round(n) | 四舍五入 | `3.14159 |
tojson | 转 JSON | `data |
#3. 条件判断
#3.1 if / elif / else
{% if user.is_logged_in %}
<p>欢迎,{{ user.name }}!</p>
{% if user.is_admin %}
<a href="/admin">管理后台</a>
{% elif user.is_editor %}
<a href="/editor">编辑后台</a>
{% else %}
<a href="/profile">个人中心</a>
{% endif %}
{% else %}
<a href="/login">登录</a>
<a href="/register">注册</a>
{% endif %}#3.2 运算符
{% if user.age >= 18 %}
<p>成年人</p>
{% endif %}
{% if article.category == "Python" and article.views > 1000 %}
<span class="hot">热门文章</span>
{% endif %}
{% if user.role not in ["banned", "deleted"] %}
<p>可以发言</p>
{% endif %}
{% if value is defined %}
<p>变量已定义</p>
{% endif %}
{% if user is none %}
<p>用户不存在</p>
{% endif %}#4. 循环(for 循环)
#4.1 基础循环
<ul>
{% for article in articles %}
<li>
<a href="{{ url_for('article', id=article.id) }}">
{{ article.title }}
</a>
<span>{{ article.views }} 阅读</span>
</li>
{% endfor %}
</ul>#4.2 循环特殊变量
{% for article in articles %}
<div class="article">
<!-- 循环计数(从1开始)-->
<span>第 {{ loop.index }} 篇</span>
<!-- 判断首/尾元素 -->
{% if loop.first %}
<span class="badge">置顶</span>
{% endif %}
<!-- 反向计数 -->
<span>剩余 {{ loop.revindex }} 篇</span>
<!-- 总数 -->
<span>({{ loop.length }} 篇中)</span>
<h2>{{ article.title }}</h2>
</div>
{% endfor %}#4.3 遍历字典
{% for key, value in user.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}#4.4 循环与条件结合
{% for article in articles %}
{% if article.published %}
<div>{{ article.title }}</div>
{% endif %}
{% else %}
<!-- 循环为空时执行 -->
<p>暂无文章</p>
{% endfor %}#5. 宏(Macro)
#5.1 定义宏
<!-- templates/macros.html -->
{% macro render_form_field(field) %}
<div class="form-group">
{{ field.label }}
{{ field(class="form-control") }}
{% if field.errors %}
<small class="error">{{ field.errors[0] }}</small>
{% endif %}
</div>
{% endmacro %}
{% macro render_article_card(article) %}
<div class="card">
<h3>{{ article.title }}</h3>
<p>{{ article.summary }}</p>
<a href="{{ url_for('article', id=article.id) }}">阅读更多</a>
</div>
{% endmacro %}#5.2 导入宏
<!-- templates/articles.html -->
{% from "macros.html" import render_article_card, render_form_field %}
{% for article in articles %}
{{ render_article_card(article) }}
{% endfor %}#6. 自动转义
#6.1 什么是自动转义?
<!-- Flask 默认自动转义 HTML -->
{{ "<script>alert('xss')</script>" }}
<!-- 输出:<script>alert...(不会被执行为 JS) -->
<!-- 取消转义(仅在信任内容时使用)-->
{{ "<b>粗体</b>"|safe }}#6.2 块级转义
{% raw %}
{# 整块内容不进行模板解析 #}
{{ this_will_be_literal }}
{% endraw %}#7. 模板中使用 Python 代码
<!-- Jinja2 支持的 Python 操作 -->
<!-- 三元表达式 -->
{{ user.name if user else "匿名用户" }}
<!-- 字符串格式化 -->
{{ "ID: %s" % user.id }}
<!-- in 操作符 -->
{% if "python" in article.tags %}
<span>Python相关</span>
{% endif %}
<!-- 取反 -->
{% if not user.is_banned %}
<p>可以发言</p>
{% endif %}#8. 小结
Jinja2 核心语法:
{{ variable }} 输出变量
{{ name|upper }} 过滤器
{% if cond %} 条件
{% for item in list %} 循环
{% macro name() %} 宏定义
{% include "file.html" %}包含模板
{{ url_for('func') }} 反向生成 URL
{{ session['key'] }} 访问 session
{{ request.args.get('q') }} 访问请求参数💡 最佳实践:在模板中只做展示,不写复杂业务逻辑。复杂的计算和判断放在视图函数或自定义 Jinja2 扩展中处理。
🔗 扩展阅读

