FastAPI+SQLAlchemy多对多查询返回元组引发验证错误求助
问题解决:多对多关系查询返回元组导致FastAPI验证失败
问题根源
你的查询结果返回的是单元素元组列表(如(<Buyer(...)>,)),而非Buyer对象列表。这是因为SQLAlchemy的Result.all()会返回完整的查询行,当仅查询单个实体时,每行是一个包含该实体的元组。Pydantic模型期望直接接收ORM对象,因此无法从元组中读取属性,导致验证错误。
修复步骤
1. 修正查询结果提取方式
将result.all()替换为result.scalars().all(),scalars()会提取每行的第一个元素(即Buyer对象),返回纯实体列表:
async def get_all_buyers(self, session: AsyncSession): statement = ( select(Buyer) .options(selectinload(Buyer.hs_codes)) .order_by(desc(Buyer.created_at)) ) result = await session.exec(statement) # 用scalars().all()替代all(),获取实体对象列表 buyers = result.scalars().all() return buyers
2. 修正代码缩进
你的return buyers语句存在缩进错误(比上一行多了额外空格),需确保它与函数内其他代码处于同一缩进级别,避免因缩进导致逻辑错误。
额外优化建议
DateTime字段类型匹配:你的Pydantic模型中
created_at和updated_at定义为str,但SQLAlchemy模型是DateTime类型。建议将Pydantic模型中的类型改为datetime,FastAPI会自动将其序列化为ISO格式字符串:from datetime import datetime class BuyerResponseModel(BaseModel): company_name: str region: str country: str city: str company_size: str hs_codes: List[HSCodeResponse] created_at: datetime updated_at: datetime class Config: from_attributes = True移除Mixin表名冲突:你的
TimestampMixin中用@declared_attr定义了__tablename__,但Buyer类又显式指定了表名,建议移除Mixin中的表名定义,避免潜在冲突:class TimestampMixin(object): # 移除这部分表名定义 # @declared_attr # def __tablename__(cls): # return cls.__name__.lower() created_at = mapped_column(DateTime, nullable=False, server_default=func.now()) updated_at = mapped_column( DateTime, nullable=False, server_default=func.now(), onupdate=func.now() )
验证修复
修改后重新测试接口,查询结果会返回Buyer对象列表,Pydantic可以正常解析其属性,生成符合要求的JSON响应。
内容的提问来源于stack exchange,提问作者MStudley
相关产品推荐
相关产品推荐

