使用Flask+SQLAlchemy+Marshmallow时dump多对象返回空数组问题
序列化空对象数组问题的原因与解决方案
问题原因
SQLAlchemy 2.x版本里,session.execute()返回的是Result对象,调用.all()得到的是Row对象的列表——每个Row都是包含Game模型实例的元组(比如(Game(id=1,...),))。你的GameSchema是为Game实例设计的,直接把Row对象列表传给games_schema.dump()时,Marshmallow找不到Row对象里的id、settlement_name等字段,自然返回空对象数组。
而用.first()时,得到的是单个Row元组,games_schema(many=True)会遍历这个元组,序列化里面的Game实例,所以能输出正确结果。
解决方案
有两种简单的修复方式:
方式1:用scalars()直接提取模型实例
修改获取游戏数据的代码,通过scalars()拿到Game实例的迭代器,再转成列表:
findGamesStatement = select(Game).filter_by(player_id = playerObject[0].id) games = masdb.session.execute(findGamesStatement).scalars().all() results = games_schema.dump(games)
方式2:手动从Row中取出模型实例
如果不想改查询逻辑,可以遍历Row列表,把每个元组里的Game实例提出来:
findGamesStatement = select(Game).filter_by(player_id = playerObject[0].id) game_rows = masdb.session.execute(findGamesStatement).all() games = [row[0] for row in game_rows] results = games_schema.dump(games)
额外优化
获取玩家对象的代码也可以用scalars()简化,不用再取索引:
findPlayerStatement = select(Players).filter_by(game_key = cookieGame_Key) playerObject = masdb.session.execute(findPlayerStatement).scalars().first() # 直接用playerObject.id即可 findGamesStatement = select(Game).filter_by(player_id = playerObject.id)
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

