如何在FastAPI中为Handlebars.js模板注入数据并返回HTML响应
在FastAPI中用Handlebars渲染HTML及其他模板引擎实现方案
一、用Python版Handlebars(pybars3)实现后端渲染
1. 安装依赖
pip install pybars3 fastapi uvicorn
2. 调整模板文件(index.html)
移除前端Handlebars编译逻辑,保留纯模板结构:
<!DOCTYPE html> <html> <head> <title>用户信息</title> </head> <body> <div class="entry"> {{#if user}} {{#each user}} <ul> <li>{{first_name}}</li> <li>{{last_name}}</li> <li>{{fav_lang}}</li> <li>{{experience}}</li> </ul> {{/each}} {{/if}} </div> </body> </html>
注:原数据结构中第二个user对象无
first_name/last_name,渲染时会显示空值,可根据需求调整数据结构或模板逻辑。
3. 修改FastAPI路由代码
from fastapi import FastAPI from fastapi.responses import HTMLResponse import pybars import os app = FastAPI() # 读取并编译Handlebars模板 template_path = os.path.join(os.path.dirname(__file__), "index.html") with open(template_path, "r", encoding="utf-8") as f: template_source = f.read() compiler = pybars.Compiler() template = compiler.compile(template_source) @app.get("/render-to-html", response_class=HTMLResponse) def read_item(first_name: str, last_name: str, fav_lang: str, exp: int): result = { "user": [ {"first_name": first_name, "last_name": last_name}, {"fav_lang": fav_lang, "experience": exp} ] } # 渲染模板并返回HTML rendered_html = template(result) return HTMLResponse(content=rendered_html)
如果需要前端渲染(后端返回带数据的页面,由前端JS完成渲染),可修改路由如下:
from fastapi import FastAPI from fastapi.responses import HTMLResponse import os import json app = FastAPI() template_path = os.path.join(os.path.dirname(__file__), "index.html") with open(template_path, "r", encoding="utf-8") as f: template = f.read() @app.get("/render-to-html", response_class=HTMLResponse) def read_item(first_name: str, last_name: str, fav_lang: str, exp: int): result = { "user": [ {"first_name": first_name, "last_name": last_name}, {"fav_lang": fav_lang, "experience": exp} ] } # 将数据注入前端JS上下文 rendered_template = template.replace( 'var context = {};', f'var context = {json.dumps(result)};' ) return HTMLResponse(content=rendered_template)
此方式无需修改原index.html,前端JS会自动读取注入的数据完成渲染。
二、其他模板引擎实现方案
1. Jinja2(FastAPI官方推荐)
Jinja2是Python生态最常用的模板引擎,FastAPI提供原生支持。
安装依赖
pip install jinja2 fastapi uvicorn
创建templates/index.html模板
<!DOCTYPE html> <html> <head> <title>用户信息</title> </head> <body> <div class="entry"> {% if user %} {% for item in user %} <ul> {% if item.first_name %}<li>{{ item.first_name }}</li>{% endif %} {% if item.last_name %}<li>{{ item.last_name }}</li>{% endif %} {% if item.fav_lang %}<li>{{ item.fav_lang }}</li>{% endif %} {% if item.experience %}<li>{{ item.experience }}</li>{% endif %} </ul> {% endfor %} {% endif %} </div> </body> </html>
路由代码
from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates from fastapi.responses import HTMLResponse app = FastAPI() templates = Jinja2Templates(directory="templates") @app.get("/render-to-html", response_class=HTMLResponse) def read_item(request: Request, first_name: str, last_name: str, fav_lang: str, exp: int): result = { "user": [ {"first_name": first_name, "last_name": last_name}, {"fav_lang": fav_lang, "experience": exp} ] } return templates.TemplateResponse("index.html", {"request": request, **result})
2. Mako模板引擎
Mako是一款灵活轻量的Python模板引擎。
安装依赖
pip install mako fastapi uvicorn
创建templates/index.html模板
<!DOCTYPE html> <html> <head> <title>用户信息</title> </head> <body> <div class="entry"> % if user: % for item in user: <ul> % if 'first_name' in item: <li>${item['first_name']}</li> % endif % if 'last_name' in item: <li>${item['last_name']}</li> % endif % if 'fav_lang' in item: <li>${item['fav_lang']}</li> % endif % if 'experience' in item: <li>${item['experience']}</li> % endif </ul> % endfor % endif </div> </body> </html>
路由代码
from fastapi import FastAPI from fastapi.responses import HTMLResponse from mako.template import Template import os app = FastAPI() template_path = os.path.join(os.path.dirname(__file__), "templates", "index.html") template = Template(filename=template_path) @app.get("/render-to-html", response_class=HTMLResponse) def read_item(first_name: str, last_name: str, fav_lang: str, exp: int): result = { "user": [ {"first_name": first_name, "last_name": last_name}, {"fav_lang": fav_lang, "experience": exp} ] } rendered_html = template.render(**result) return HTMLResponse(content=rendered_html)
内容的提问来源于stack exchange,提问作者Sumit Kashyap
相关产品推荐
相关产品推荐

