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

Marshmallow-sqlalchemy加载主键数据触发AttributeError错误求助

问题排查与解决

问题核心

使用SQLAlchemyAutoSchema(开启load_instance=True)加载包含主键的数据时,触发AttributeError: 'DummySession' object has no attribute 'get'错误,仅加载非主键字段时正常。

环境与代码背景

  • 依赖版本:
    marshmallow-sqlalchemy==1.0.0
    SQLAlchemy==2.0.30
    flask-marshmallow==1.2.1
    
  • Schema定义:
    from flask_marshmallow import Marshmallow
    
    ma = Marshmallow(app)
    
    class TicketSchema(ma.SQLAlchemyAutoSchema):
        class Meta:
            model = db_models.TicketModel
            load_instance = True
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for field_name, field in self.fields.items():
                field.required = False
    
  • 模型通过automap_base反射生成(对应SQL Server的Ticket表,主键TicketId)。
  • 触发错误的代码:
    data = {"TicketId": "123"}
    TicketSchema().load(data)
    

错误原因

当开启load_instance=True时,marshmallow-sqlalchemy会尝试通过会话查找数据库中已存在的匹配主键的实例。如果未显式传入SQLAlchemy会话,库会使用内部的DummySession类,但marshmallow-sqlalchemy 1.0.0未适配SQLAlchemy 2.x的API——SQLAlchemy 2.x将get作为会话核心方法,而DummySession并未实现该方法。

解决方案

方案1:显式传入真实SQLAlchemy会话

在初始化Schema或调用load方法时,传入Flask-SQLAlchemy的会话对象:

# 假设你使用flask-sqlalchemy,db是实例
from your_app import db

# 方式1:初始化Schema时传入session
schema = TicketSchema(session=db.session)
schema.load(data)

# 方式2:调用load时传入session
TicketSchema().load(data, session=db.session)

方案2:升级marshmallow-sqlalchemy到兼容版本

marshmallow-sqlalchemy 1.1.0及以上版本已适配SQLAlchemy 2.x,升级后DummySession会实现get方法:

pip install marshmallow-sqlalchemy>=1.1.0

方案3:禁用实例查找(仅创建新实例)

如果不需要从数据库加载已有实例,仅需生成新模型对象,可修改Schema的Meta类添加include_fk=False:

class TicketSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = db_models.TicketModel
        load_instance = True
        include_fk = False  # 阻止Schema尝试通过主键查找实例

方案4:重写Schema的get_instance方法

如果无法升级依赖或传入会话,可重写方法跳过数据库查找:

class TicketSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = db_models.TicketModel
        load_instance = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.required = False

    def get_instance(self, data):
        # 跳过数据库查找,直接返回None,Schema会创建新实例
        return None

内容的提问来源于stack exchange,提问作者Sederfo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:35:08