如何获取不含主键的ORM模型数据并解决对象更新报错问题?
问题解决:SQLAlchemy模型更新错误及非主键数据获取
错误原因
你遇到的AttributeError: 'NoteORM' object has no attribute 'items',是因为误将SQLAlchemy模型对象当作字典使用(比如调用了需要字典items()方法的操作)。模型对象本身不是字典结构,自然没有这个方法。
如何获取不含主键的模型数据
推荐两种可靠的方法,避免直接操作__dict__带来的内部属性干扰:
方法1:使用SQLAlchemy inspect工具
通过inspect可以精准获取模型的列元数据,筛选出非主键字段:
from sqlalchemy import inspect def get_non_pk_fields(entity): # 获取模型类的元数据 insp = inspect(entity.__class__) # 筛选非主键列的键名 return [col.key for col in insp.columns if not col.primary_key] # 使用示例 entity = session.query(NoteORM).get(11) non_pk_fields = get_non_pk_fields(entity) # 拿到非主键字段对应的数据 non_pk_data = {field: getattr(entity, field) for field in non_pk_fields}
方法2:直接从模型表结构筛选
通过模型的__table__.columns直接获取列信息,筛选非主键:
def get_non_pk_fields(model_cls): return [col.name for col in model_cls.__table__.columns if not col.primary_key] # 使用示例 non_pk_fields = get_non_pk_fields(NoteORM) entity = session.query(NoteORM).get(11) non_pk_data = {field: getattr(entity, field) for field in non_pk_fields}
说明:你之前的props方法直接遍历__dict__.keys(),会包含SQLAlchemy内部属性(比如_sa_instance_state),且未过滤主键,所以会拿到NoteID。另外模型对象的__dict__中主键是不带下划线的,_NoteID是内部私有属性,直接使用会报错。
模型对象更新的最优方法
根据不同场景选择合适的方式:
1. 单个对象更新(最常用)
直接获取对象后修改属性,SQLAlchemy会自动跟踪变化,最后提交会话即可:
entity = session.query(NoteORM).get(11) # 直接修改需要更新的属性 entity.Note = "更新后的笔记内容" entity.IsSend = "已发送" # 提交会话,完成更新 session.commit()
这种方式最直观,SQLAlchemy会自动生成仅修改变化字段的UPDATE语句,性能最优。
2. 字典批量赋值更新
如果需要用字典批量更新属性,可通过setattr循环赋值:
update_data = {"Note": "批量更新的内容", "IsSend": "已发送"} entity = session.query(NoteORM).get(11) for key, value in update_data.items(): setattr(entity, key, value) session.commit()
3. 批量更新多个对象
如果要一次性更新符合条件的多个对象,直接使用查询的update方法(注意传字典而非模型对象):
# 将接收者ID为1的所有笔记标记为已发送 session.query(NoteORM).filter(NoteORM.Reciver == 1).update({"IsSend": "已发送"}) session.commit()
这种方式会生成单条UPDATE语句,比循环更新多个对象效率高很多。
内容的提问来源于stack exchange,提问作者Django
相关产品推荐
相关产品推荐

