FastAPI配合SQLAlchemy使用session时列表append/remove失效如何修复
问题原因
你的问题核心是SQLAlchemy默认不会追踪可变类型(如ARRAY、JSON字段存储的列表、字典)的原地修改操作,append、remove都属于对列表对象的原地修改,会话无法检测到字段值发生了变化,因此提交时不会生成对应的更新语句。
另外你贴的第一版代码还存在3个明显笔误:
- 数据库会话变量名拼写错误,
deb.query应为db.query - Python相等判断语法错误,
===应为== - 未定义的变量调用,
db_post_likes没有提前赋值,相当于你append操作之后又用未知值覆盖了likes字段,直接导致append结果被清空。
修复方案
方案1:启用可变类型变更追踪(推荐)
直接修改模型字段定义,给可变类型加上SQLAlchemy提供的可变修饰符,后续所有原地修改都会被自动追踪:
如果是PostgreSQL原生ARRAY类型:
from sqlalchemy import ARRAY, String from sqlalchemy.ext.mutable import MutableList # 模型字段定义 likes = Column(MutableList.as_mutable(ARRAY(String)), default=list, nullable=False)
如果是通用JSON类型存储列表:
from sqlalchemy import JSON from sqlalchemy.ext.mutable import MutableList # 模型字段定义 likes = Column(MutableList.as_mutable(JSON), default=list, nullable=False)
修改后你原来的append写法删除多余的setattr行就可以正常运行:
db_post = db.query(models.Post).filter(models.Post.id == post.id).first() db_post.likes.append(email) db.commit() db.refresh(db_post) return db_post
方案2:修改后手动标记字段变更
如果不想修改模型定义,可以在原地修改完成后手动通知会话字段已修改:
from sqlalchemy.orm.attributes import flag_modified db_post = db.query(models.Post).filter(models.Post.id == post.id).first() db_post.likes.append(email) # 手动标记likes字段存在变更 flag_modified(db_post, "likes") db.commit() db.refresh(db_post) return db_post
方案3:原地修改后重新赋值
修改完列表后重新给字段赋值整个列表对象,赋值操作会被会话直接检测到变更:
db_post = db.query(models.Post).filter(models.Post.id == post.id).first() db_post.likes.append(email) # 重新赋值触发变更检测 db_post.likes = db_post.likes db.commit() db.refresh(db_post) return db_post
内容的提问来源于stack exchange,提问作者LCW
相关产品推荐
相关产品推荐

