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宏,实现模板逻辑复用。模板中可直接使用requestsessiongconfigurl_forget_flashed_messages六个内置对象,无需显式传递。掌握这些API,你就能在Flask应用中灵活构建动态HTML页面。

相关推荐
摇滚侠1 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC容器的高级机制 Environment 阅读笔记 4
spring boot·笔记·后端
2601_962387821 小时前
Python CUDA 编程 - 2 - Numba 简介
python·numpy·cuda·jit编译器·numba
豆角焖肉1 小时前
Spring Boot入门实战:从零搭建第一个应用
java·spring boot·后端·自动配置
mldong3 小时前
Go 开发者也有自己的轻量工作流引擎了:go get 一行,5 分钟跑通一条审批流
后端·go
BingoGo9 小时前
PHP clone 之后,为什么改副本会影响原对象?
后端·php
JaguarJack9 小时前
PHP clone 之后,为什么改副本会影响原对象?
后端·php·服务端
智能体与具身智能10 小时前
TVA具身智能的概念、架构与应用(19)
人工智能·python·具身智能
小灰灰搞电子10 小时前
Rust+Slint 实现动态消息提示框源码分享
开发语言·后端·rust
小奏技术10 小时前
10 MB 的 Postman 替代品,启动不到 1 秒
后端