FastAPI页面切换异常:点击返回按钮无法渲染初始表单页
问题分析
你遇到的核心问题是:当通过innerHTML替换整个页面HTML内容时,浏览器不会自动执行新HTML中的<script>标签代码。从结果页返回表单页后,form.html里的submit()函数没有被定义,导致表单看似渲染但无法正常工作(或你感知到“无法渲染”)。
另外注意到你代码里的模板目录拼写为templetes(正确拼写应为templates),如果实际目录名和代码不一致会导致模板加载失败,建议统一修正。
解决方法
方法一:保持无刷新体验,手动执行脚本
这种方法保留当前的无刷新替换逻辑,但在替换HTML后手动提取并执行新页面的脚本:
修改result.html的脚本
<script> function displayHTML() { fetch("/", { method: "GET" }) .then(response => response.text()) .then(html => { const htmlElement = document.getElementsByTagName("html")[0]; htmlElement.innerHTML = html; // 提取并执行新页面中的所有脚本 const scripts = htmlElement.getElementsByTagName("script"); Array.from(scripts).forEach(script => { const newScript = document.createElement("script"); if (script.src) { newScript.src = script.src; } else { newScript.textContent = script.textContent; } document.head.appendChild(newScript); // 执行后移除临时脚本,避免重复加载 newScript.remove(); }); }); } window.displayHTML = displayHTML; </script>
修改form.html的脚本(确保submit函数全局可访问)
<script> // 将submit函数绑定到window,避免作用域问题 window.submit = function() { const name = document.getElementById("first").value; const date = document.getElementById("dob").value; fetch("/result", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: name, date: date }) }) .then(response => response.text()) .then(html => { const htmlElement = document.getElementsByTagName("html")[0]; htmlElement.innerHTML = html; // 同样执行结果页的脚本 const scripts = htmlElement.getElementsByTagName("script"); Array.from(scripts).forEach(script => { const newScript = document.createElement("script"); if (script.src) { newScript.src = script.src; } else { newScript.textContent = script.textContent; } document.head.appendChild(newScript); newScript.remove(); }); }) } </script>
方法二:改用页面跳转(更简单可靠)
如果不需要严格的无刷新体验,直接用window.location.href跳转,浏览器会完整加载页面并自动执行所有脚本,实现起来更简单:
调整后端代码(支持GET请求返回结果页)
from fastapi import FastAPI, Request, Query from fastapi.templating import Jinja2Templates from pydantic import BaseModel app = FastAPI() # 修正模板目录拼写(如果实际目录是templates的话) templates = Jinja2Templates(directory="templates") class InputData(BaseModel): name : str date : str # 新增GET接口支持参数传递 @app.get("/result") async def get_result_get(request: Request, name: str = Query(...), date: str = Query(...)): data = { "name": name, "dob": date } return templates.TemplateResponse("result.html", {"request": request, "data": data}) # 保留原POST接口 @app.post("/result") async def get_result_post(request: Request, input: InputData): data = { "name": input.name, "dob": input.date } print(data) return templates.TemplateResponse("result.html", {"request": request, "data": data}) @app.get("/") async def root(request : Request): return templates.TemplateResponse("form.html" , {"request" : request})
修改form.html的submit函数
<script> function submit() { const name = document.getElementById("first").value; const date = document.getElementById("dob").value; // 跳转到结果页并传递参数 window.location.href = `/result?name=${encodeURIComponent(name)}&date=${encodeURIComponent(date)}`; } </script>
修改result.html的返回按钮
<button onclick="window.location.href = '/'">Back</button>
总结
- 方法一适合需要无刷新体验的场景,但需要处理脚本执行逻辑;
- 方法二更简单可靠,兼容性更好,适合大多数普通Web场景。
内容的提问来源于stack exchange,提问作者Gaurav Monga
相关产品推荐
相关产品推荐

