FastAPI+SQLAlchemy ORM更新报错:TypeError: Query.update()参数异常
解决FastAPI中SQLAlchemy ORM更新记录的TypeError问题
错误原因
你遇到的TypeError是因为SQLAlchemy的Query.update()方法要求传入字典格式的参数,而非直接传递关键字参数(如title=request.title);另外db.refresh()只能作用于ORM模型实例,不能用于Query对象。
正确实现方式
以下提供两种常用的正确更新方案:
方案1:使用Query.update()(批量更新风格)
from fastapi import HTTPException, status, Depends from sqlalchemy.orm import Session import models from schemas import TodoRequest, TodoResponse @app.put('/todos/{id}', status_code=status.HTTP_202_ACCEPTED, response_model=TodoResponse) def update_todo(id: int, request: TodoRequest, db: Session = Depends(get_db)): todo_query = db.query(models.Todo).filter(models.Todo.id == id) todo = todo_query.first() if not todo: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"todo with id {id} not found.") # 将Pydantic模型转为字典,exclude_unset=True只更新请求中提供的字段 update_data = request.dict(exclude_unset=True) todo_query.update(update_data) db.commit() # 刷新实例获取最新数据库数据 db.refresh(todo) return todo
方案2:直接修改ORM实例属性(直观ORM风格)
from fastapi import HTTPException, status, Depends from sqlalchemy.orm import Session import models from schemas import TodoRequest, TodoResponse @app.put('/todos/{id}', status_code=status.HTTP_202_ACCEPTED, response_model=TodoResponse) def update_todo(id: int, request: TodoRequest, db: Session = Depends(get_db)): todo = db.query(models.Todo).filter(models.Todo.id == id).first() if not todo: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"todo with id {id} not found.") # 批量赋值,只更新请求中传入的字段 for key, value in request.dict(exclude_unset=True).items(): setattr(todo, key, value) # 也可以手动逐个赋值(适合字段少的场景) # todo.title = request.title # todo.completed = request.completed db.commit() db.refresh(todo) return todo
关键注意事项
- 使用
request.dict(exclude_unset=True)可以避免覆盖未在请求中传入的字段(比如请求只传了title,就不会修改completed的现有值) - 必须先通过
first()获取模型实例,才能使用db.refresh()刷新数据 - 不能直接将Pydantic模型对象传给
update(),必须转为字典格式
内容的提问来源于stack exchange,提问作者NAVEED SHAHZAD
相关产品推荐
相关产品推荐

