Flask入门教程(附录):模板渲染API——Jinja2集成全解析

1. render_template ------ 最常用的模板渲染函数

render_template()从文件加载模板并渲染,返回HTML字符串。

参数 类型 说明
template_name_or_list str / list 模板文件名(相对于templates/文件夹),或模板名列表(返回第一个存在的)
**context 关键字参数 传递给模板的变量,如title="Hello"、user=user_obj
复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    return render_template(
        "index.html",
        title="RUNOOB 首页",
        posts=[
            {"id": 1, "title": "文章A"},
            {"id": 2, "title": "文章B"}
        ]
    )

# 模板列表(按顺序查找第一个存在的)
@app.route("/user/<username>")
def user_profile(username):
    # 优先使用用户自定义模板,不存在则使用默认模板
    return render_template(
        [f"users/{username}.html", "users/default.html"],
        username=username
    )

2. 全部渲染函数

函数 说明
render_template(template_name_or_list, **context) 从文件渲染模板,返回HTML字符串
render_template_string(source, **context) 从字符串渲染模板,适用于嵌入式模板
stream_template(template_name_or_list, **context) 流式渲染模板,返回生成器,适用于大型页面
stream_template_string(source, **context) 流式渲染字符串模板
get_template_attribute(template_name, attribute) 获取模板中的宏或变量,可从Python调用Jinja2宏

2.1 render_template_string ------ 字符串模板

复制代码
from flask import Flask, render_template_string

app = Flask(__name__)

@app.route("/inline")
def inline_template():
    # 模板内容直接写在代码中
    return render_template_string("""
        <!DOCTYPE html>
        <html>
        <head>
            <title>{{ title }} - RUNOOB</title>
        </head>
        <body>
            <h1>Hello, {{ name }}!</h1>
            <p>Welcome to RUNOOB.</p>
            {% if user %}
                <p>当前用户:{{ user }}</p>
            {% endif %}
        </body>
        </html>
    """, title="首页", name="World", user="runoob")

2.2 stream_template ------ 流式渲染

适用于大型页面,边生成边发送给客户端,减少内存占用和首屏等待时间。

复制代码
from flask import Flask, stream_template

app = Flask(__name__)

@app.route("/stream")
def stream_large_page():
    # 流式渲染大页面,边生成边发送
    return stream_template(
        "large_report.html",
        items=range(10000)  # 1万条数据,流式发送
    )

2.3 stream_template_string ------ 流式渲染字符串模板

复制代码
from flask import Flask, stream_template_string

app = Flask(__name__)

@app.route("/stream-inline")
def stream_inline():
    return stream_template_string("""
        <h1>流式渲染</h1>
        {% for i in range(1000) %}
            <p>项目 {{ i + 1 }}</p>
        {% endfor %}
    """)

2.4 get_template_attribute ------ 获取模板中的宏

可以从Python代码中调用Jinja2宏,实现模板逻辑复用。

复制代码
from flask import Flask, get_template_attribute

app = Flask(__name__)

# templates/macros.html
# {% macro render_item(item) %}
#     <li class="item">{{ item.name }} ({{ item.price }})</li>
# {% endmacro %}

@app.route("/use-macro")
def use_macro():
    # 获取模板中的宏
    render_item = get_template_attribute("macros.html", "render_item")
    
    # 在Python中调用宏
    items = [{"name": "商品A", "price": 99}, {"name": "商品B", "price": 199}]
    html = "".join([render_item(item) for item in items])
    
    return f"<ul>{html}</ul>"

3. 模板中的内置对象

以下对象在模板中无需显式传递即可使用:

对象 说明 模板中使用示例
request 当前请求对象 {``{ request.path }}、{``{ request.args.get('q') }}
session 当前Session对象 {``{ session.get("username") }}
g 请求级全局对象 {``{ g.user.name }}
config 应用配置字典 {``{ config["APP_NAME"] }}
url_for URL生成函数 {``{ url_for("index") }}
get_flashed_messages Flash消息获取函数 {% for msg in get_flashed_messages() %}

模板示例

复制代码
<!-- templates/dashboard.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ config.get("APP_NAME", "RUNOOB") }}</title>
</head>
<body>
    <h1>欢迎, {{ session.get("username", "访客") }}!</h1>
    
    <p>当前路径: {{ request.path }}</p>
    <p>用户IP: {{ request.remote_addr }}</p>
    
    {% if g.user %}
        <p>用户等级: {{ g.user.level }}</p>
    {% endif %}
    
    <p><a href="{{ url_for("logout") }}">退出登录</a></p>
    
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            {% for category, msg in messages %}
                <div class="flash-{{ category }}">{{ msg }}</div>
            {% endfor %}
        {% endif %}
    {% endwith %}
</body>
</html>

4. 模板渲染完整示例

复制代码
from flask import (
    Flask, render_template, render_template_string,
    stream_template, stream_template_string,
    get_template_attribute, session, g, request
)

app = Flask(__name__)
app.secret_key = "dev-secret"

# 模拟数据
USER_DATA = {
    "username": "runoob",
    "email": "test@runoob.com",
    "level": "admin",
    "posts": [
        {"id": 1, "title": "Flask 入门", "views": 1024},
        {"id": 2, "title": "Jinja2 模板", "views": 512},
        {"id": 3, "title": "RESTful API", "views": 256},
    ]
}

# ============ 1. render_template ============
@app.route("/")
def index():
    session["username"] = USER_DATA["username"]
    g.user = USER_DATA
    return render_template(
        "index.html",
        title="RUNOOB 博客",
        posts=USER_DATA["posts"]
    )

# ============ 2. render_template_string ============
@app.route("/inline")
def inline():
    return render_template_string("""
        <!DOCTYPE html>
        <html>
        <head><title>{{ title }}</title></head>
        <body>
            <h1>{{ title }}</h1>
            <p>当前用户:{{ session.get("username", "访客") }}</p>
            <ul>
            {% for post in posts %}
                <li>{{ post.title }} (浏览 {{ post.views }})</li>
            {% endfor %}
            </ul>
        </body>
        </html>
    """, title="RUNOOB 教程", posts=USER_DATA["posts"])

# ============ 3. stream_template ============
@app.route("/stream")
def stream():
    return stream_template(
        "stream.html",
        items=[{"id": i, "name": f"商品{i}"} for i in range(1000)]
    )

# ============ 4. get_template_attribute ============
@app.route("/macro")
def macro_demo():
    render_item = get_template_attribute("macros.html", "render_item")
    items = [{"name": f"商品{chr(65+i)}", "price": (i+1) * 10} for i in range(5)]
    html = "".join([render_item(item) for item in items])
    return f"""
    <!DOCTYPE html>
    <html>
    <head><title>宏调用示例</title></head>
    <body>
        <h1>商品列表</h1>
        <ul>{html}</ul>
    </body>
    </html>
    """

# ============ 5. 模板列表(回退) ============
@app.route("/user/<username>")
def user_page(username):
    # 优先使用用户专属模板,不存在则使用默认模板
    return render_template(
        [f"users/{username}.html", "users/default.html"],
        username=username,
        user=USER_DATA
    )

5. 模板渲染API速查表

函数 说明 适用场景
render_template("file.html", **context) 从文件渲染模板 最常用,所有常规页面
render_template_string("{``{ code }}", **context) 从字符串渲染模板 嵌入式模板、动态模板
stream_template("file.html", **context) 流式渲染(生成器) 大数据量页面
stream_template_string("{``{ code }}", **context) 流式渲染字符串模板 大数据量嵌入式模板
get_template_attribute("file.html", "macro") 获取模板宏/变量 Python调用Jinja2宏

6. 内置对象速查表

对象 模板中使用 说明
request {``{ request.path }} 当前请求信息
session {``{ session.get("key") }} 用户会话数据
g {``{ g.user.name }} 请求级共享数据
config {``{ config["KEY"] }} 应用配置
url_for {``{ url_for("index") }} 生成URL
get_flashed_messages {% for msg in get_flashed_messages() %} 获取Flash消息

7. 常见错误与最佳实践

❌ 错误做法 ✅ 正确做法
模板路径写绝对路径 使用相对templates/的路径
在模板中硬编码URL 使用{``{ url_for("endpoint") }}
忘记传递模板变量导致UndefinedError 使用`{``{ var
在模板中直接使用session.user 先判断{% if session.user %}
将模板文件放在非templates/目录 创建应用时指定template_folder

小结

本章全面讲解了Flask模板渲染的完整API。render_template()是从文件渲染模板的核心函数,支持传递任意关键字参数作为模板变量;render_template_string()从字符串渲染模板,适用于嵌入式模板;stream_template()和stream_template_string()支持流式渲染大页面,边生成边发送,减少内存占用;get_template_attribute()可从Python调用Jinja2宏,实现模板逻辑复用。模板中可直接使用request、session、g、config、url_for、get_flashed_messages六个内置对象,无需显式传递。掌握这些API,你就能在Flask应用中灵活构建动态HTML页面。

相关推荐
顽疲9 小时前
Java vue 养老系统源码详解:楼宇床位 care_space 与房态图 Spring Boot 实践
后端
小小张说故事9 小时前
CatBoost 入门指南:类别特征为什么不用 One-Hot?Python 实战与 5 个坑
python·机器学习
Lyy9 小时前
DevOps平台 — 第十三篇:规划的设计与实现
后端·devops
今天不在线9 小时前
旧 Java 项目接入 AI 实战系列(一):四层递进,从基础对话到流式输出
后端
卷无止境9 小时前
WebGIS生态全景丨从浏览器里的地图到背后的空间数据库
后端·python
Y3815326629 小时前
竞品上新监控:用搜索 API 盯住对手发布了什么新功能
python·搜索引擎
benchmark_cc9 小时前
如何设计一个 Python 实时行情获取程序?从轮询、数据处理到量化策略接入
python·数据分析·pandas·量化交易·股票数据·quantdash
JuiceFS9 小时前
JuiceFS 企业版 5.4:从千亿文件到百万客户端
后端
Metaphor6929 小时前
Python 实现 Word/TXT 互转:附完整代码
python·word·格式转换·txt
Lost of 程序猿9 小时前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式