
本文讲解如何在 FastAPI 中通过前端 JavaScript 正确提交表单数据(POST),获取响应结果,并跳转到新页面(如 /books)同时携带数据,避免 AttributeError: 'Body' object has no attribute 'casefold' 等常见错误。
本文讲解如何在 fastapi 中通过前端 javascript 正确提交表单数据(post),获取响应结果,并跳转到新页面(如 `/books`)同时携带数据,避免 `attributeerror: 'body' object has no attribute 'casefold'` 等常见错误。
✅ 正确做法是:分离关注点——先用 POST 获取数据,再跳转页面,并将结果暂存于客户端(如 sessionStorage),供目标页读取。
✅ 修正后的完整流程
1. 后端:优化 get_books 接口(接收 JSON 字段 info)
from fastapi import Body, Request, HTTPException
from fastapi.responses import JSONResponse
@app.post("/get_books")
async def get_books(info: str = Body(..., embed=True)): # ✅ 显式声明 info 为字符串,且嵌套在 JSON body 中
book_list = []
for book in BOOKS:
title = book.get("title", "").casefold()
author = book.get("author", "").casefold()
category = book.get("category", "").casefold()
if info.casefold() in [title, author, category]:
book_list.append(book)
return {"books": book_list} # ✅ 返回结构化 JSON,便于前端解析
⚠️ 注意:Body(..., embed=True) 表示期望请求体为 {"info": "xxx"};若前端发送的是裸字符串(如 JSON.stringify(info)),则改用 Body(..., media_type="text/plain") 并配合 await request.body() 手动解析。
2. 前端:POST 后存储数据并跳转(关键修复)
<!-- 移除默认 href,防止意外 GET --> <a id="btn" class="main__arrow" href="javascript:void(0)"> <i class="fa-solid fa-arrow-right"></i> </a> <input type="text" id="prompt" placeholder="搜索书名/作者/分类">
const btn = document.getElementById('btn');
btn.addEventListener('click', async function () {
const promptValue = document.getElementById("prompt").value.trim();
if (!promptValue) return;
try {
const response = await fetch("/get_books", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ info: promptValue }) // ✅ 匹配后端 embed=True 结构
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
// ✅ 存入 sessionStorage(页面跳转后仍可用,关闭标签页即销毁)
sessionStorage.setItem("searchResult", JSON.stringify(data.books));
// ✅ 安全跳转
window.location.href = "/books";
} catch (err) {
console.error("搜索失败:", err);
}
});
3. 前端 /books 页面:读取并渲染数据
在 books.html 中添加初始化逻辑:
<script>
document.addEventListener("DOMContentLoaded", () => {
const books = JSON.parse(sessionStorage.getItem("searchResult") || "[]");
const container = document.getElementById("book-list");
if (books.length === 0) {
container.innerHTML = "<p>未找到匹配的图书。";
return;
}
const html = books.map(book => `
<div class="book">
<h3>${book.title}
<p>作者:${book.author}|分类:${book.category}
`).join("");
container.innerHTML = html;
// ✅ 清理 sessionStorage,避免重复使用
sessionStorage.removeItem("searchResult");
});
</script><div id="book-list"></div>
4. (可选)后端 /books 路由:精简逻辑
@app.get("/books", response_class=HTMLResponse)
async def books(request: Request):
# ✅ 不再调用 get_books() —— 数据已由前端 POST 获取并缓存
return templates.TemplateResponse("books.html", {"request": request})
? 关键要点总结
- ❌ 错误模式: + 在 /books 中调用需 POST 参数的函数 → 必然报错;
- ✅ 正确模式:JS 主动 fetch POST → 缓存结果 → window.location.href 跳转 → 目标页读取缓存;
- sessionStorage 是理想选择:同源、页面级生命周期、无需服务端状态管理;
- 后端接口应明确参数类型(str = Body(...)),避免隐式解析异常;
- 前端务必处理空值、网络错误及 JSON 解析异常,提升健壮性。
通过以上重构,即可实现“输入 → 搜索 → 跳转 → 展示”的流畅用户体验,同时保持 FastAPI 路由职责清晰、前后端解耦。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










