首页
/ FastAPI 服务端渲染实战:基于 Jinja2Templates 的模板渲染、url_for 与静态资源服务

FastAPI 服务端渲染实战:基于 Jinja2Templates 的模板渲染、url_for 与静态资源服务

2026-09-04 21:44:49作者:毕习沙Eudora

在 FastAPI 中渲染 HTML 页面时,官方文档 docs/de/docs/advanced/templates.md 给出了一套标准方案:通过 Starlette 提供的 Jinja2Templates 工具类完成 Jinja2 模板的服务端渲染,并结合 StaticFiles 处理样式、脚本等静态资源。读完本篇,你将掌握如何安装配置模板依赖、编写可复用的模板对象、向模板注入上下文变量、在模板内部用 url_for() 生成正确链接,以及验证渲染结果的完整方法。

可以自由选择模板引擎

FastAPI 本身并不绑定任何特定的模板引擎——你可以使用任意你喜欢的引擎。最常见的选择是 Jinja2,也就是 Flask 等主流 Python Web 框架所使用的同一款引擎。

FastAPI(经由 Starlette 提供)内置了便于直接集成的配置工具,你几乎不需要手动初始化 Jinja2 环境。

安装依赖

模板渲染功能依赖 jinja2 包,将其加入项目即可:

$ uv add jinja2

---> 100%

使用 Jinja2Templates 渲染页面

整个流程包含四个步骤:

  1. 导入 Jinja2Templates
  2. 创建一个 templates 对象,后续在多个路径操作中复用;
  3. 在返回模板的 路径操作 中声明一个 Request 参数;
  4. 调用 templates.TemplateResponse(),传入模板名称、请求对象和一个"上下文"字典(键值对将被注入 Jinja2 模板中),渲染并返回 TemplateResponse

仓库中的完整示例见 教程示例代码

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")


templates = Jinja2Templates(directory="templates")


@app.get("/items/{id}", response_class=HTMLResponse)
async def read_item(request: Request, id: str):
    return templates.TemplateResponse(
        request=request, name="item.html", context={"id": id}
    )

参数顺序的变化(FastAPI 0.108.0 / Starlette 0.29.0)

需要注意版本兼容性问题:

  • 在 FastAPI 0.108.0 和 Starlette 0.29.0 之前,name(模板文件名)是 TemplateResponse第一个位置参数
  • 更早的版本中,request 对象是作为上下文键值对的一部分传给 Jinja2 的,而不是独立的 request= 关键字参数。

因此在新版中应采用 TemplateResponse(request=..., name=..., context=...) 的关键字参数形式(如上例所示),以兼容当前版本。

声明 response_class=HTMLResponse 的价值

示例中路由装饰器显式声明了 response_class=HTMLResponse。这样做让交互式文档界面(Swagger UI)能够知道该端点的响应是 HTML 而非 JSON,从而在文档中正确展示响应类型。

fastapi.templatingstarlette.templating 的关系

源码层面可以直接印证这一点:查看 fastapi/templating.py,整个文件只有一行:

from starlette.templating import Jinja2Templates as Jinja2Templates  # noqa

也就是说,你既可以写 from fastapi.templating import Jinja2Templates,也可以写 from starlette.templating import Jinja2Templates,二者完全等价——FastAPI 只是把 Starlette 的 starlette.templatingfastapi.templating 的名义再导出一次,作为开发上的便利。同理,RequestStaticFiles 等能力也直接来自 Starlette。

编写模板文件

接下来在 templates/item.html 中编写模板。仓库中的实际模板文件见 item.html

<html>
<head>
    <title>Item Details</title>
    <link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet">
</head>
<body>
    <h1><a href="{{ url_for('read_item', id=id) }}">Item ID: {{ id }}</a></h1>
</body>
</html>

模板上下文值(Context Values)

模板中这一行:

Item ID: {{ id }}

其值 id 取自你在调用 TemplateResponse 时传入的"上下文"字典:

{"id": id}

假设请求的 ID 为 42,该行将渲染为:

Item ID: 42

这就是模板上下文注入的核心机制:context 字典中的每个键都成为模板中可直接引用的变量名。

模板中的 url_for() 用法

你同样可以在模板内部使用 url_for(),它接收的命名参数与你路径操作函数的参数一致。上面的模板片段:

<a href="{{ url_for('read_item', id=id) }}">

生成的正是由路径操作函数 read_item(id=id) 所处理的 URL。当 ID 为 42 时渲染结果为:

<a href="/items/42">

这样做的好处是:链接由路由系统统一生成,即使将来路径前缀或路由模式变化,模板中的链接依然正确,无需手动拼接字符串。

模板与静态文件

url_for() 还可以配合以 name="static" 挂载的 StaticFiles 使用,这正是上面模板第 4 行的写法:

<link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet">

在本示例中,它指向 static/styles.css,内容为:

h1 {
    color: green;
}

由于挂载了 StaticFiles(见示例中 app.mount("/static", StaticFiles(directory="static"), name="static")),该 CSS 文件会自动由 FastAPI 应用在 URL /static/styles.css 处对外提供服务,模板中的 url_for('static', ...) 会生成指向该 URL 的链接。

测试验证:渲染结果如何被断言

仓库中的 模板测试 展示了如何验证整套流程:

def test_main():
    # ... 将 docs_src 下的模板与静态文件复制到工作目录 ...
    from docs_src.templates.tutorial001_py310 import app

    client = TestClient(app)
    response = client.get("/items/foo")
    assert response.status_code == 200, response.text
    assert (
        b'<h1><a href="http://testserver/items/foo">Item ID: foo</a></h1>'
        in response.content
    )
    response = client.get("/static/styles.css")
    assert response.status_code == 200, response.text
    assert b"color: green;" in response.content

测试验证了两件事:

  1. GET /items/foo 返回 200,且响应体包含由 url_for('read_item', id=id) 生成的完整绝对 URL(测试服务器地址为 http://testserver/items/foo)与上下文变量渲染出的 Item ID: foo——这印证了 url_for 生成的链接是绝对 URL(含 scheme 和 host),在模板中直接可用;
  2. GET /static/styles.css 返回 200 且包含 color: green;,印证了 StaticFiles 挂载后的静态资源自动服务行为。

小结

本篇覆盖了文档的全部核心内容:

  • 使用 uv add jinja2 安装模板引擎依赖;
  • 通过 Jinja2Templates(directory="templates") 创建可复用的模板对象;
  • 路径操作声明 Request 参数后,用 TemplateResponse(request=..., name=..., context=...) 渲染并返回 HTML(注意 0.108.0 前后的参数顺序差异);
  • 通过 response_class=HTMLResponse 让文档 UI 正确识别 HTML 响应;
  • 用上下文字典向模板注入变量,用 url_for() 在模板中生成路径操作和静态文件链接;
  • StaticFiles 挂载静态目录并自动对外服务;
  • 通过 TestClient 断言渲染结果完成验证。

如需进一步了解模板测试等更多细节,可参考 Starlette 官方的 templates 文档。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
980
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384