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
相关产品推荐
相关产品推荐

