SQLAlchemy 1.4异步JOIN查询无法同时获取两张关联表数据问题
问题原因
scalars() 方法的设计逻辑就是仅提取结果行中第一个位置的实体/字段,当你在select()中传入多个实体时,每行查询结果是包含多个ORM实例的元组,调用scalars()会默认丢弃元组中除第一个外的其他数据,这就是你只能拿到单个表数据的核心原因。
解决方案
以下是两种常用的可行方案:
- 方案1:直接调用结果集的
all()方法获取完整行数据
不需要加scalars()调用,直接从执行结果中取all(),每行返回的是对应select()参数顺序的ORM实例元组,可以直接解包使用:# 执行查询的语句保持不变 stmt = select(Resource, UserResourceRole).join(UserResourceRole) result = await async_session.execute(stmt) # 直接调用all()获取完整行数据 rows = result.all() # 遍历解包使用 for resource, user_role in rows: print(resource.id, user_role.permission) - 方案2:通过ORM关系预加载关联数据(更符合ORM使用规范)
先在你的Resource模型中定义和UserResourceRole的关联关系:
查询时使用from sqlalchemy.orm import relationship class Resource(Base): __tablename__ = "resource" # 原有字段定义保持不变... # 定义和中间表的关联关系 user_roles = relationship("UserResourceRole", back_populates="resource") class UserResourceRole(Base): __tablename__ = "user_resource_role" # 原有字段定义保持不变... resource_id = Column(ForeignKey("resource.id")) resource = relationship("Resource", back_populates="user_roles")joinedload预加载关联数据,查出来的Resource实例会直接携带对应的权限数据:from sqlalchemy.orm import joinedload stmt = select(Resource).join(Resource.user_roles).options(joinedload(Resource.user_roles)) result = await async_session.execute(stmt) # 因为返回的第一个实体是Resource,可用scalars()提取,加unique()去重一对多关联产生的重复行 resources = result.scalars().unique().all() # 直接访问关联权限即可 for resource in resources: print(resource.id, [role.permission for role in resource.user_roles])
注意事项
- 如果你的查询需要返回指定字段而非完整ORM实例,可以在
select()中明确列出对应字段,同样直接用all()获取每行的字段值元组即可。 - 异步场景下上述两种方案都完全兼容,不需要额外调整会话逻辑。
内容的提问来源于stack exchange,提问作者mlisthenewcool
相关产品推荐
相关产品推荐

