如何将SQL Alchemy ORM实例转换为dict,使用__dict__出现KeyError如何解决
问题原因
- SQLAlchemy ORM实例的
__dict__属性不是纯用户字段集合,除了内部维护的_sa_instance_state状态属性外,未被访问过的懒加载字段、延迟加载字段不会主动写入__dict__的首层键,直接取对应字段键自然会抛出KeyError。 - 如果你查询实例时用了
load_only、defer这类方法过滤了返回字段,或者实例是刚创建还未执行flush操作,也会出现对应字段不在__dict__中的情况。
修复方案
方案1:通过mapper元数据获取字段(最稳定,兼容所有SQLAlchemy版本)
直接用模型自带的mapper元数据拿定义的字段,再用getattr取值,完全不依赖__dict__的结构:
def trial_to_dict(sa_trial_instance): """Convert a SQL Alchemy instance to a JSON dict params: sa_trial_instance (object): SQL Alchemy model instance returns: dict: JSON serializable dict with target fields """ # 只取需要的字段,避免返回多余属性 target_fields = ("ct_id", "study_type", "phase") return { col.key: getattr(sa_trial_instance, col.key) for col in sa_trial_instance.__mapper__.columns if col.key in target_fields }
方案2:兼容__dict__写法的修复版
如果你一定要沿用__dict__的实现逻辑,可以增加属性兜底获取逻辑,避免KeyError:
def trial_to_dict(sa_trial_instance): """Convert a SQL Alchemy instance to a JSON dict params: sa_trial_instance (object): SQL Alchemy model instance returns: dict: JSON serializable dict with target fields """ # 先过滤掉SQLAlchemy内部属性 temp_dict = {k: v for k, v in sa_trial_instance.__dict__.items() if not k.startswith("_sa_")} return { "ct_id": temp_dict.get("ct_id", getattr(sa_trial_instance, "ct_id")), "study_type": temp_dict.get("study_type", getattr(sa_trial_instance, "study_type")), "phase": temp_dict.get("phase", getattr(sa_trial_instance, "phase")) }
内容的提问来源于stack exchange,提问作者Vivian
相关产品推荐
相关产品推荐

