手把手教你用Jinja2打造动态Web页面

张开发
2026/4/3 16:39:39 15 分钟阅读
手把手教你用Jinja2打造动态Web页面
一、问题与背景FastAPI只能“吃”JSONFastAPI以构建高性能API闻名return JSONResponse几乎是肌肉记忆。但很多场景下比如- 快速原型开发搞个带页面的demo。- 内部管理后台复杂度不高不想动用前端框架。- 需要服务端渲染SSR的简单页面。这时候你硬要前后端彻底分离反而有种“杀鸡用牛刀”的繁琐。就好比你只想在家门口吃碗面结果非要开车去市中心的高级餐厅点单、等餐、打包再回来。模板引擎就是让你在FastAPI这个“高性能厨房”里直接开个“堂食窗口”。Jinja2就是这个窗口最得力的伙计它能把你的数据肉、菜和HTML模板碗、汤底快速组合成一碗热腾腾的面最终页面。 二、核心原理与步骤“两条腿”走路好咱们先来解决最核心的问题数据怎么从后端“走”到模板里核心就两步1. 配置引擎2. 传递数据。数据传递有两条关键“路径”我画个灵魂图示给你看路径A依赖项注入全局/请求级上下文在路由处理函数里通过TemplateResponse的context参数传递。这是最常用、最灵活的方式数据针对每次请求。路径B全局模板上下文每个模板都能用在初始化Jinja2Templates时通过context参数传递。比如站点名、当前年份等全局通用数据。是不是有点抽象别急咱们接着看实战代码一写你就全明白了。 三、实战演示从零搭建一个用户列表页接下来重点来了咱们一步步来。假设我们要做一个显示用户列表的页面。1️⃣ 安装与项目结构先安装必备库pip install fastapi jinja2 uvicorn项目目录结构建议这样安排清晰明了 your_project/ ├── templates/ # 存放所有Jinja2 HTML模板 │ └── index.html ├── static/ # 存放CSS, JS, 图片等静态文件 │ └── style.css └── main.py # FastAPI 主应用文件2️⃣ 配置FastAPI与Jinja2在main.py里进行初始化。这里有个关键点directory参数必须是字符串路径不能是Path对象Jinja2的老规矩。from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from fastapi.staticfiles import StaticFiles app FastAPI(titleFastAPIJinja2 Demo) # 配置模板引擎告诉它模板文件在哪 templates Jinja2Templates(directorytemplates) # 配置静态文件服务挂载到/static路径 app.mount(/static, StaticFiles(directorystatic), namestatic)3️⃣ 定义路由与传递数据路径A我们定义一个路由模拟从数据库获取用户列表并传递给模板app.get(/, response_classHTMLResponse) async def read_users(request: Request): # 模拟数据实际中可能来自数据库 user_list [ {id: 1, name: 张三, role: 管理员}, {id: 2, name: 李四, role: 编辑}, {id: 3, name: 王五, role: 订阅用户}, ] # 网站标题作为额外数据传递 site_title 内部用户管理系统 # 核心操作渲染模板并通过context传递数据 return templates.TemplateResponse( requestrequest, nameindex.html, # 模板文件名 context{ request: request, # 这个必须有Jinja2Templates要求 users: user_list, title: site_title } )千万注意context字典里必须包含 request 键这是Jinja2Templates的工作机制要求的不然模板里一些基于请求的功能会失效。4️⃣ 编写模板文件 (templates/index.html)看看数据在模板里怎么用!DOCTYPE html html langzh-CN head meta charsetUTF-8 title{{ title }}/title !-- 重点引入静态CSS文件 -- link relstylesheet href{{ url_for(static, path/style.css) }} /head body h1欢迎使用 {{ title }}/h1 table border1 thead tr thID/th th姓名/th th角色/th /tr /thead tbody {% for user in users %} tr td{{ user.id }}/td td{{ user.name }}/td td{{ user.role }}/td /tr {% endfor %} /tbody /table /body /html敲黑板引入静态文件用的是url_for(static, path/style.css)。这里的static对应我们app.mount时设置的namestatic。这是我初期常配错的地方name必须一致5️⃣ 编写静态文件 (static/style.css)随便写点样式确认它能被加载body { font-family: sans-serif; padding: 20px; background-color: #f5f5f5; } h1 { color: #2c3e50; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; text-align: left; } thead { background-color: #3498db; color: white; }好了现在运行uvicorn main:app --reload打开http://127.0.0.1:8000一个带样式和动态数据的用户列表页面就出来了数据从后端“流”到了前端静态文件也正常加载。⚠️ 四、注意事项与进阶思考是不是以为这样就完了再说几个容易翻车的点。 避坑指南1. 静态文件404- 检查app.mount的directory路径是否正确相对路径从项目根目录算起。- 检查模板中url_for的name参数是否与mount的name一致。- 生产环境通常用Nginx等专门处理静态文件开发时用StaticFiles很方便。2. 全局上下文路径B怎么用比如你想在每个页面都显示版权年份templates Jinja2Templates( directorytemplates, context{current_year: 2024} # 全局注入 ) # 然后在任何模板里都可以直接使用 {{ current_year }} 进阶思考模板继承是王牌用{% extends base.html %}和{% block content %}...{% endblock %}来复用布局如导航栏、页脚能让你的模板代码干净十倍。强烈建议你用起来。

更多文章