FastAPI报value is not a valid dict错误但数据已插入数据库
核心错误原因
你的POST接口指定了response_model=Checkpoint,但接口返回的是MongoDB的InsertOneResult对象(即insert_one方法的返回结果),而非符合Checkpoint模型结构的字典/对象。FastAPI在尝试将返回值序列化为Checkpoint类型时,因类型不匹配抛出value is not a valid dict错误。而数据能成功插入,是因为collections.insert_one()已经执行完成,错误仅出现在返回结果的序列化阶段。
代码修复步骤
1. 修正create_checkpoint的返回值
修改crud.py中的create_checkpoint函数,插入数据后返回符合Checkpoint模型的对象:
async def create_checkpoint(checkpoint): document = checkpoint result = await collections.insert_one(document) # 查询刚插入的文档并转换为Checkpoint模型返回 inserted_doc = await collections.find_one({"_id": result.inserted_id}) return Checkpoint(**inserted_doc)
或者如果不需要从数据库拉取,直接返回传入的验证后的对象:
async def create_checkpoint(checkpoint): await collections.insert_one(checkpoint) return Checkpoint(**checkpoint)
2. 统一数据库字段名
你的模型字段是Name(大写N),但update_checkpoint、remove_checkpoint中的查询条件用的是{'name': name}(小写n),这会导致后续更新、删除操作失效。统一修改为大写Name:
# crud.py - update_checkpoint async def update_checkpoint(name, lat, lon): # 合并一次update操作,减少数据库交互 await collections.update_one( {'Name': name}, {"$set": {'Latitude': lat, 'Longitude': lon}} ) document = await collections.find_one({'Name': name}) return document # crud.py - remove_checkpoint async def remove_checkpoint(name): await collections.delete_one({'Name': name}) return True
3. 修正路由格式
你的GET/PUT/DELETE路由缺少路径分隔符,比如/api/checkpoint{name}应该改为/api/checkpoint/{name},否则FastAPI无法正确解析路径参数:
# main.py 修正后的路由示例 @app.get("/api/checkpoint/{name}", response_model=Checkpoint) async def get_checkpoint_by_id(name): response = await fetch_one_checkpoint(name) if response: return response raise HTTPException(404, f"There is no checkpoint: {name}") @app.put("/api/checkpoint/{name}", response_model=Checkpoint) async def put_checkpoint(name: str, lat: float, lon: float): response = await update_checkpoint(name, lat, lon) if response: return response raise HTTPException(404, f"There is no checkpoint: {name}") @app.delete("/api/checkpoint/{name}") async def delete_checkpoint(name): response = await remove_checkpoint(name) if response: return {"message": "Successfully deleted checkpoint"}
注:DELETE接口原指定了response_model=Checkpoint,但返回的是字符串,会导致序列化错误,建议移除该参数,返回自定义成功信息。
其他说明
你之前尝试的checkpoint.dict()、dict(checkpoint)是正确的传参方式,问题不在传入数据,而在返回数据的类型不匹配。
内容的提问来源于stack exchange,提问作者Gusbc

