如何用Python+FastAPI+SQLAlchemy实现用户表任意字段Patch更新?
解决FastAPI+SQLAlchemy Patch接口更新用户字段的问题
你遇到的TypeError: 'UserModel' object does not support item assignment是因为SQLAlchemy的模型实例是类对象,不能像字典那样用[]赋值,得用属性访问或者setattr()函数。另外代码里还有几处逻辑问题,下面是完整的修复方案:
1. 优化UserToUpdate的定义(更简洁)
不用重复定义字段,利用Pydantic的特性直接生成全可选的Schema:
如果是Pydantic v2:
from pydantic import ConfigDict class UserToUpdate(UserSchema): model_config = ConfigDict(from_attributes=True, partial=True)
如果是Pydantic v1:
class UserToUpdate(UserSchema): class Config: orm_mode = True partial = True
这样自动把UserSchema里的所有字段设为可选,不用手动逐个声明Optional。
2. 修复Patch路由函数
主要修改点:用setattr()赋值、修正用户存在判断逻辑、过滤未传入的字段
@user_router.patch('/{id}', status_code=status.HTTP_200_OK, response_model=UserSchema) async def update_user(id: int, data: UserToUpdate, db: AsyncSession = Depends(get_session)): async with db as session: # 查询目标用户 result = await session.execute(select(UserModel).filter(UserModel.id == id)) user_to_update = result.scalar() # 判断用户是否存在 if not user_to_update: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Usuário não encontrado') # 只更新用户实际传入的字段 for key, value in data.model_dump(exclude_unset=True).items(): setattr(user_to_update, key, value) await session.commit() # 刷新实例确保返回最新数据 await session.refresh(user_to_update) return user_to_update
关键修改说明
- 替换字典赋值为setattr:SQLAlchemy模型是类实例,必须用
setattr(obj, attr_name, value)动态设置属性,不能用obj[key]的字典操作方式。 - 用model_dump(exclude_unset=True):只提取用户实际传入的字段,自动忽略未提交的可选字段,比直接遍历
__dict__更安全,避免把未传入的字段更新为None。 - 修正用户存在判断:
result是查询执行结果对象,永远不会为None,应该判断user_to_update(scalar()返回的模型实例,不存在则为None)。 - session.refresh():提交后刷新实例,确保返回的对象是数据库中的最新状态,避免返回旧数据。
内容的提问来源于stack exchange,提问作者Alojarf
相关产品推荐
相关产品推荐

