You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 19:36:03