异步SQLAlchemy+FastAPI一对多关联查询报错求助
解决SQLAlchemy异步查询中关联集合预加载的InvalidRequestError错误
直接修改异步接口的结果处理逻辑,添加unique()方法即可解决问题,完整代码如下:
@router.get("/testing", response_model=List[WebsiteOut], response_model_exclude_none=True) async def all_websites( user_filter: WebsiteFilter = FilterDepends(WebsiteFilter), session: AsyncSession = Depends(get_session) ): query = select(Websites) query = query.distinct() query = query.join(Websites.website_services) query = query.options(contains_eager(Websites.website_services)) query = query.filter(WebsiteServices.disabled == False) query = user_filter.filter(query) query = user_filter.sort(query) result = await session.execute(query) return result.scalars().unique().all()
原因解析
当通过contains_eager预加载一对多关联集合(如Websites.website_services)并执行JOIN查询时,SQL会返回多条包含重复父对象的结果行(每个子对象对应一行)。虽然你在SQL层面添加了distinct()去重,但ORM层面需要进一步处理对象实例的去重与聚合,确保每个Websites对象仅返回一次,同时正确组装其关联的服务集合。
同步模式下的db.query(Websites).all()会自动处理这个对象去重逻辑,而异步模式使用Core风格的select查询时,必须显式调用unique()方法触发ORM层面的去重,否则就会抛出InvalidRequestError。
效果验证
修改后,异步接口将返回与同步版本完全一致的结果:
[ { "url": "https://www.******.com", "tat": 10, "website_services": [ { "service_name": "cbd", "service_cost": 250, "website_id": 26 }, { "service_name": "guest_post", "service_cost": 100, "website_id": 26 } ] }, { "url": "https://www.*************.com", "tat": 10, "website_services": [ { "service_name": "guest_post", "service_cost": 150, "website_id": 13 } ] } ]
内容的提问来源于stack exchange,提问作者Erez Bentovim
相关产品推荐
相关产品推荐

