如何在FastAPI的Jinja2模板中将Python函数传入JavaScript
解决方案:通过API接口+流式响应实现需求
你遇到的核心问题是Python函数无法直接传递给前端JavaScript执行——两者运行在不同环境,服务器端的Python对象没法直接序列化为可执行的JS代码。正确的做法是把需要执行的逻辑封装成FastAPI接口,前端通过HTTP请求调用它,同时利用FastAPI的流式响应实现进度条更新。
步骤1:后端实现(FastAPI)
把你的Python函数逻辑封装成支持流式返回进度的API接口,用StreamingResponse配合yield实时推送进度数据:
from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates from fastapi.responses import StreamingResponse import asyncio import json app = FastAPI() templates = Jinja2Templates(directory="templates") # 模拟带进度的业务任务 async def run_task_with_progress(): total_steps = 10 for step in range(total_steps): # 替换成你的实际业务逻辑 await asyncio.sleep(0.5) # 生成JSON格式的进度数据,换行分隔便于前端解析 yield json.dumps({"progress": (step+1)*10}) + "\n" @app.get("/") async def read_root(request: Request): # 无需传递函数到模板,直接返回页面 return templates.TemplateResponse("index.html", {"request": request}) @app.get("/execute-task") async def execute_task(): # 返回流式响应,支持实时推送进度 return StreamingResponse(run_task_with_progress(), media_type="text/event-stream")
步骤2:前端模板(index.html)
通过JavaScript的fetch调用后端接口,监听流式响应并更新进度条:
<!DOCTYPE html> <html> <head> <title>进度条示例</title> <style> .progress-bar { width: 300px; height: 20px; border: 1px solid #ccc; margin-top: 10px; } .progress-fill { height: 100%; background-color: #4CAF50; width: 0%; transition: width 0.3s; } </style> </head> <body> <button onclick="startTask()">开始执行任务</button> <div class="progress-bar"> <div class="progress-fill" id="progressFill"></div> </div> <div id="status"></div> <script> async function startTask() { const progressFill = document.getElementById('progressFill'); const status = document.getElementById('status'); // 调用后端任务接口 const response = await fetch('/execute-task'); const reader = response.body.getReader(); const decoder = new TextDecoder(); status.textContent = "任务执行中..."; while (true) { const { done, value } = await reader.read(); if (done) break; // 解析每一块进度数据并更新DOM const data = JSON.parse(decoder.decode(value)); const progress = data.progress; progressFill.style.width = `${progress}%`; status.textContent = `进度:${progress}%`; if (progress === 100) { status.textContent = "任务完成!"; } } } </script> </body> </html>
关键说明
- 函数传递的本质问题:Python函数是服务器端内存对象,无法被序列化为前端可执行的代码,必须通过HTTP请求触发执行。
- 流式响应的作用:
StreamingResponse+yield可以让后端逐步返回进度数据,前端无需等待整个任务完成就能实时更新进度条。 - 前端流式数据处理:通过
response.body.getReader()逐块读取后端返回的内容,解析后直接更新页面元素。
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

