[Python] FastAPI: pydantic validation error when returning model class

Discussão em 'Python' iniciado por Stack, Março 12, 2025.

  1. Stack

    Stack Membro Participativo

    I'm using FastAPI, SQLModel and SQLAlchemy to build an API. I have the following model classes:

    BaseModel

    class CategoryBase(SQLModel):
    name: str = Field(nullable=False, max_length=255)
    position: int = Field(nullable=False, default=0)


    DbModel

    class Category(CategoryBase, table=True):
    __tablename__ = "category"
    id: int | None = Field(primary_key=True)


    ReturnModel

    class CategoryModel(BaseModel):
    id: int
    name: str
    position: int



    I want my API endpoint to return a list of CategoryModel with the following code:

    @categories_router.get("", response_model=List[CategoryModel])
    async def get_categories(*, session: Session = SessionDep):
    categories = session.exec(
    select(Category).order_by(Category.position)
    ).all()

    return categories


    However when I run the endpoint, I get the following error message:

    fastapi.exceptions.ResponseValidationError: 2 validation errors:
    {'type': 'missing', 'loc': ('response', 0, 'name'), 'msg': 'Field required', 'input': (Category(name='Einstieg', id=1, position=1),)}
    {'type': 'missing', 'loc': ('response', 0, 'id'), 'msg': 'Field required', 'input': (Category(name='Einstieg', id=1, position=1),)}


    During debugging I found out that the data is loaded correctly: [​IMG]

    The id, name and position attributes are loaded correctly.

    When removing the response_model attribute from the decorator, I get the follwing error message:

    ValueError: [ValueError('dictionary update sequence element #0 has length 3; 2 is required'), TypeError('vars() argument must have __dict__ attribute')]


    When using the deprecated query function, it does work as intended:

    @categories_router.get("", response_model=List[CategoryModel])
    async def get_categories(*, session: Session = SessionDep):
    categories = session.query(Category).order_by(Category.position).all()
    return categories


    This is the correct response:

    [
    {
    "id": 1,
    "name": "Einstieg",
    "position": 1
    }
    ]


    When using session.execute, it also works:

    @categories_router.get("", response_model=List[CategoryModel])
    async def get_categories(*, session: Session = SessionDep):
    result = session.execute(
    select(Category).order_by(Category.position)
    ).scalars().all()

    return result


    But session.execute is also deprecated. I don't want to use the deprecated API, but the documentation doesn't give me any indication of what is going wrong. What am I missing?

    Continue reading...

Compartilhe esta Página