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页面。