Flask SQLAlchemy多对多反序列化出现dict无_sa_instance_state报错
错误原因
'dict' object has no attribute '_sa_instance_state'报错的核心原因是:Marshmallow默认反序列化嵌套的roles字段时返回字典列表,而SQLAlchemy的User模型的roles关系字段要求接收Role模型实例列表,普通字典没有SQLAlchemy实例必需的_sa_instance_state属性,因此触发错误。
修复步骤
- 修复UserSchema的语法错误
原UserSchema的fields配置存在引号错位问题,先修正:
class UserSchema(ma.SQLAlchemyAutoSchema): roles = ma.Nested(RoleSchema, many=True) class Meta: load_instance = True # 修正roles字段的引号位置 fields = ("id", "first_name", "last_name", "access_id", "email", "roles", "password") model = User
- 配置RoleSchema返回模型实例
给RoleSchema添加load_instance配置,让嵌套的角色字段反序列化时直接返回Role模型实例而非字典:
class RoleSchema(ma.SQLAlchemyAutoSchema): class Meta: fields = ("id", "role") model = Role load_instance = True # 新增本行配置
可选优化(关联已有角色场景)
如果业务逻辑中Role是预先配置好的公共数据,创建用户时只需关联已存在的Role、不需要新建Role,建议手动处理roles字段避免重复创建角色数据,修改post接口代码如下:
def post(self): try: body = request.get_json() # 单独提取roles参数,查询已存在的角色实例 role_list = body.pop("roles", []) user = user_schema.load(body) # 赋值查询到的角色实例 user.roles = [Role.query.get(item["id"]) for item in role_list if Role.query.get(item["id"])] user.hash_password() db.session.add(user) db.session.commit() return {'id': str(user.id)}, 200 except Exception as e: # 新增异常回滚逻辑,避免脏数据 db.session.rollback() return {"msg": "创建用户失败"}, 400
内容的提问来源于stack exchange,提问作者RuSs
相关产品推荐
相关产品推荐

