如何通过SQLAlchemy获取多对多关联关系中的完整关联数据
如何通过SQLAlchemy获取多对多关联关系中的完整关联数据
嗨,我完全懂你的困惑!你现在用SQLAlchemy的多对多关联,靠RsDetail这个关联表连接Player和Rslevel,但查询时只能拿到关联表的ID值,没法直接访问关联的玩家和等级详情,对吧?
问题出在你当前的查询逻辑上:你直接选择了RsDetail这个表对象,虽然做了多表join,但SQLAlchemy只会返回RsDetail的行数据——毕竟你没明确告诉它要把关联的Player和Rslevel实体也加载进来呀!
下面给你两种可行的解决方案:
第一种:修改查询语句,明确包含关联实体
你可以调整select语句,把Player、Rslevel和RsDetail都纳入查询范围,这样执行后就能拿到包含这三个对象的元组,直接访问对应属性:stmt = select(Player, Rslevel, RsDetail).join( RsDetail, Player.id == RsDetail.c.playerId ).join( Rslevel, RsDetail.c.rslevelId == Rslevel.id ).join( Guild, Rslevel.guild_id == Guild.id ).where(Guild.discord_id == guild_id) rs_list = session.execute(stmt).all() # 遍历结果,元组顺序和select里的实体顺序一致 for player, rslevel, rsdetail in rs_list: print(player.name, rslevel.level) # 要是需要用RsDetail自身的字段,比如id,直接用rsdetail.id即可第二种:把RsDetail从Table改成ORM模型类(更推荐)
如果你希望能像rs.player.name这样直接访问关联属性,更建议把RsDetail改成完整的ORM模型类,而不是单纯的Table对象,这样可以直接定义到Player和Rslevel的关联关系:# 替换原来的RsDetail Table定义为模型类 class RsDetail(Base): __tablename__ = 'RsDetail' id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) playerId: Mapped[int] = mapped_column(Integer, ForeignKey('players.id')) rslevelId: Mapped[int] = mapped_column(Integer, ForeignKey('rslevel.id')) # 定义到Player和Rslevel的关联关系 player: Mapped["Player"] = relationship("Player") rslevel: Mapped["Rslevel"] = relationship("Rslevel")同时需要调整Player和Rslevel类里的relationship配置(因为现在关联表是模型类了):
# Player类中的rs关系修改为 rs: Mapped[list["Rslevel"]] = relationship(secondary="RsDetail", back_populates="players") # Rslevel类中的players关系修改为 players: Mapped[list["Player"]] = relationship(secondary="RsDetail", back_populates="rs")这样修改后,你的查询语句可以简化,而且结果里的RsDetail对象会直接带有player和rslevel属性,完全符合你想要的访问方式:
stmt = select(RsDetail).join(Rslevel).join(Player).join(Guild).where(Guild.discord_id == guild_id) rs_list = session.execute(stmt).scalars().all() for rs in rs_list: print(rs.player.name, rs.rslevel.level) # 也能直接访问RsDetail自身的字段,比如rs.id这种方式更符合ORM的使用习惯,后续如果要给RsDetail加额外字段(比如关联创建时间)也会非常方便。
备注:内容来源于stack exchange,提问作者cameleon33
相关产品推荐
相关产品推荐

