1. Flask 与 Jinja2 简介
- Flask 是一个轻量级的 Python Web 框架,默认集成了模板引擎 。
Python Flask 框架默认集成 Jinja2 模板引擎,用于将数据渲染至 HTML 页面。涵盖环境搭建、目录结构配置、模板渲染基础语法、变量与控制结构、模板继承、静态文件引用及高级特性如宏、过滤器、全局变量注入等内容。通过示例代码展示如何自定义模板路径、处理表单数据、实现国际化支持及安全转义机制,帮助开发者高效构建动态 Web 应用。

确保已安装 Flask 开发环境。Flask 会自动安装 Jinja2。
推荐结构如下:
your_project/
├── app.py
├── templates/
│ └── index.html
└── static/
└── style.css
templates/ 存放 Jinja2 模板static/ 存放静态文件(如 CSS、JS、图片)Flask 默认读取 templates/ 目录。如果你想自定义:
app = Flask(__name__, template_folder='your_templates_folder')
templates/index.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template(
'index.html',
title='首页',
name='小明',
items=['苹果', '香蕉', '橘子']
)
if __name__ == '__main__':
app.run(debug=True)
{{ variable }}{% if %} ... {% endif %},{% for %} ... {% endfor %}{# 注释内容 #}{{ name|upper }},{{ list|length }}{% if items %}
<ul>
{% for item in items %}
<li>{{ item|capitalize }}</li>
{% endfor %}
</ul>
{% else %}
<p>没有内容。</p>
{% endif %}
你可以传递字典、列表、对象等:
user = {'name': '小红', 'age': 18}
return render_template('index.html', user=user)
模板:
<p>姓名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
templates/base.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}我的网站{% endblock %}</title>
</head>
<body>
<div>
{% block content %}{% endblock %}
</div>
</body>
</html>
templates/index.html:
{% extends "base.html" %}
{% block title %}首页{% endblock %}
{% block content %}
<h1>欢迎来到首页</h1>
{% endblock %}
模板中引用静态文件:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
你可以自定义 Jinja2 的配置,例如自定义分隔符:
app.jinja_env.variable_start_string = '[['
app.jinja_env.variable_end_string = ']]'
模板中就用 [[ variable ]]。
{{ name|capitalize }} 首字母大写{{ text|safe }} 标记为安全 HTML,不会被转义{{ items|length }} 获取列表长度{{ price|round(2) }} 保留两位小数你可以在 Flask 中注册自己的过滤器:
def reverse_string(s):
return s[::-1]
app.jinja_env.filters['reverse'] = reverse_string
模板中使用:
<p>{{ name|reverse }}</p>
宏类似于模板中的函数,可以复用模板片段。
templates/macros.html:
{% macro render_input(name, type='text') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}
引用宏:
{% import "macros.html" as macros %}
{{ macros.render_input('username') }}
可以将公共片段抽取出来:
templates/header.html:
<header>
<h1>网站头部</h1>
</header>
在主模板中使用:
{% include 'header.html' %}
loop.index 当前循环索引(从 1 开始)loop.index0 当前循环索引(从 0 开始)loop.first 是否第一个元素loop.last 是否最后一个元素<ul>
{% for item in items %}
<li>{{ loop.index }}: {{ item }}</li>
{% endfor %}
</ul>
你可以为所有模板注入全局变量:
@app.context_processor
def inject_user():
return dict(site_name='我的网站')
模板中直接使用:
<p>{{ site_name }}</p>
如果模板变量不存在,默认不会报错而是显示空白。你可以用 default 过滤器:
{{ user.name|default('匿名') }}
app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/form', methods=['GET', 'POST'])
def form():
if request.method == 'POST':
username = request.form.get('username')
msg = f'你好,{username}!'
return render_template('form.html', msg=msg)
if __name__ == '__main__':
app.run(debug=True)
templates/form.html:
<form method="post">
<input type="text" name="username">
<input type="submit" value="提交">
</form>
<p>{{ msg }}</p>
开发阶段建议开启 debug=True,模板修改会自动刷新。生产环境建议关闭自动刷新以提升性能。
safe 过滤器Jinja2 默认会自动转义变量,防止 XSS 攻击。如果你确定内容安全,可以使用 safe:
{{ html_content|safe }}
如果你的项目有多个模板目录,可以这样配置:
from flask import Flask
from jinja2 import ChoiceLoader, FileSystemLoader
app = Flask(__name__)
app.jinja_loader = ChoiceLoader([
FileSystemLoader('templates'),
FileSystemLoader('more_templates')
])
Flask-Babel 可以帮助你实现模板的多语言支持:
pip install flask-babel
配置和模板用法请参考 Flask-Babel 文档。
{% set var = value %} 在模板中定义变量{% debug %} 可以打印当前上下文(需要手动扩展)your_project/
├── app.py
├── templates/
│ ├── base.html
│ ├── index.html
│ └── macros.html
├── static/
│ ├── css/
│ └── js/
├── blueprints/
│ └── user.py
└── config.py
Jinja2 支持复杂的条件表达式:
{% if score >= 90 %}
<p>优秀</p>
{% elif score >= 60 %}
<p>及格</p>
{% else %}
<p>不及格</p>
{% endif %}
还可以进行逻辑运算:
{% if user and user.is_admin %}
<p>管理员操作区</p>
{% endif %}
在模板内部可以设置变量:
{% set total = price * quantity %}
<p>总价:{{ total }}</p>
变量作用域仅限于当前块或模板,不会影响到其他地方。
基础模板 base.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<nav>
{% block nav %}默认导航{% endblock %}
</nav>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>
子模板 page.html:
{% extends "base.html" %}
{% block title %}具体页面标题{% endblock %}
{% block nav %}
<a href="/">首页</a> | <a href="/user">用户中心</a>
{% endblock %}
{% block content %}
<h1>页面内容</h1>
{% endblock %}
这样可以实现高度复用和灵活扩展。
如果你想在子模板里保留父模板的内容,可以用 {{ super() }}:
{% block nav %}
{{ super() }}
<a href="/help">帮助</a>
{% endblock %}
可以传递变量给被 include 的模板:
{% include "user_card.html" with context %}
或者只传递部分变量:
{% include "user_card.html" with user=user, show_detail=True %}
Jinja2 支持嵌套循环,但不支持 break/continue,可以通过条件控制:
{% for user in users %}
{% if user.is_active %}
<p>{{ user.name }}</p>
{% endif %}
{% endfor %}
可以用 set 定义列表或字典:
{% set colors = ['red', 'green', 'blue'] %}
{% for color in colors %}
<span>{{ color }}</span>
{% endfor %}
debug=True 时,模板修改会自动刷新。假设你有如下结构:
your_project/
├── app.py
├── user/
│ ├── __init__.py
│ └── templates/
│ └── user/
│ └── profile.html
在蓝图里渲染模板:
from flask import Blueprint, render_template
user_bp = Blueprint('user', __name__, template_folder='templates')
@user_bp.route('/profile')
def profile():
return render_template('user/profile.html')
可以用 url_for 加版本参数:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css', v='20250801') }}">
可以注册全局函数:
def greet(name):
return f'你好,{name}!'
app.jinja_env.globals['greet'] = greet
模板中使用:
<p>{{ greet('小明') }}</p>
如果你需要自定义标签,可以编写 Jinja2 Extension(需要较高水平,一般用不到)。
template_folder。{% %} 和 {{ }} 的区别。url_for 用法。app.py:
@app.route('/blog')
def blog():
posts = [
{'title': '第一篇', 'author': '小明', 'content': '内容 1'},
{'title': '第二篇', 'author': '小红', 'content': '内容 2'},
]
return render_template('blog.html', posts=posts)
templates/blog.html:
<h2>博客列表</h2>
<ul>
{% for post in posts %}
<li>
<h3>{{ post.title }}</h3>
<p>作者:{{ post.author }}</p>
<div>{{ post.content }}</div>
</li>
{% endfor %}
</ul>

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online