FastAPI分页获取用户列表时Bank字段无法返回详情的问题
问题
使用FastAPI、SQLAlchemy和Pydantic(v2)开发时,分页获取用户列表结果不符合预期:
- 预期分页返回的每个用户
bank字段包含完整银行详情 /user/me单用户接口可正常返回bank完整信息,但/users/all分页接口返回时触发Internal Server Error,报错显示bank字段输入为布尔值(True/False),无法通过Pydantic验证- 若将
UserRead中的bank字段改为bool类型,接口可正常返回布尔值,但不符合业务需求
分页数据通过FastCRUD的get_multi方法获取,尝试get_multi_joined方法也未解决问题。
相关抽象代码如下:
database.py
class Base(DeclarativeBase, MappedAsDataclass): pass
model.py
class User(Base): __tablename__ = 'users' id: Mapped[uuid_pkg.UUID] = mapped_column(default_factory=uuid_pkg.uuid4, primary_key=True, unique=True, index=True) # 其他字段省略 bank: Mapped["Bank"] = relationship("Bank", uselist=False, back_populates="user", default=None, lazy='selectin') class Bank(Base): __tablename__ = "bank" id: Mapped[uuid_pkg.UUID] = mapped_column(default_factory=uuid_pkg.uuid4, primary_key=True, unique=True, index=True) account_number: Mapped[str] = mapped_column(String(10), nullable=False, default=None) # 其他字段省略 user_id: Mapped[uuid_pkg.UUID] = mapped_column(types.Uuid, ForeignKey("users.id"), default=None) user = relationship("User", back_populates="bank")
Schema.py
class UserRead(BaseModel): id: uuid_pkg.UUID bank: Optional[BankBase] model_config = ConfigDict(from_attributes=True) class BankBase(BaseModel): name: Annotated[str, Field(min_length=2, examples=["bank name"])] account_number: Annotated[str, Field(min_length=2, max_length=10, examples=["account number"])] account_name: Annotated[str, Field(min_length=2, max_length=50, examples=["account name"])] model_config = ConfigDict(from_attributes=True)
解决方法
1. 显式配置FastCRUD的关联模型
FastCRUD的get_multi_joined需要明确指定要关联的模型,否则可能仅返回关联字段的存在性(布尔值)而非完整对象。修改分页查询代码,传入join_models参数:
from fastcrud import FastCRUD crud_user = FastCRUD(User) async def get_users_all(db: AsyncSession, skip: int = 0, limit: int = 10): return await crud_user.get_multi_joined( db=db, skip=skip, limit=limit, join_models=[Bank] # 明确指定要关联的Bank模型 )
2. 直接用SQLAlchemy主动预加载关联数据
如果FastCRUD方法仍不生效,直接构建SQLAlchemy查询,使用selectinload预加载bank关联,确保查询时一次性获取完整数据:
from sqlalchemy import select from sqlalchemy.orm import selectinload async def get_users_all(db: AsyncSession, skip: int = 0, limit: int = 10): query = select(User).options(selectinload(User.bank)).offset(skip).limit(limit) result = await db.execute(query) return result.scalars().all()
3. 验证Pydantic模型映射正确性
- 确认
BankBase定义的所有字段在Bank数据库模型中都存在,无字段名或类型不匹配 - 检查
model_config = ConfigDict(from_attributes=True)配置是否正确,确保Pydantic能从SQLAlchemy实例中读取属性值
4. 排查FastCRUD版本或默认行为
部分版本的FastCRUD处理一对一关联时,可能默认返回关联状态(布尔值)而非完整对象。可以查看FastCRUD的源码或文档,确认get_multi_joined是否需要额外配置,比如指定join_type或调整加载策略。
内容的提问来源于stack exchange,提问作者emmanuel
相关产品推荐
相关产品推荐

