Estoy intentando usar FastApi + SqlAlchemy y tengo un problema con los parámetros. Este es el error que está causando mi parámetro Post. ¿Qué estoy haciendo mal?
MENSAJE DE ERROR
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'app.models.Post'> is a valid pydantic field typeCódigo
from fastapi import FastAPI, Response, HTTPException from fastapi.params import Body, Depends from sqlalchemy.orm import Session from starlette import status from . import models from .database import engine, get_db from .models import Post models.Base.metadata.create_all(bind=engine) app = FastAPI() @app.get("/posts") def get_posts(db: Session = Depends(get_db)): posts = db.query(models.Post).all() return {"data": posts} @app.post("/posts", status_code = status.HTTP_201_CREATED) def create_posts(post: Post, db: Session = Depends(get_db)): new_post = models.Post(title=post.title, content=post.content, published=post.published) # db.add(new_post) # db.commit() # db.refresh(new_post) return {"data": new_post}Tipo de mensaje
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.sql.expression import text from sqlalchemy.sql.sqltypes import TIMESTAMP from .database import Base class Post(Base): __tablename__ = "postsalchemy" id = Column(Integer, primary_key=True, nullable=False) title = Column(String, nullable=False) content = Column(String, nullable=False) published = Column(Boolean, server_default='TRUE', nullable=False) created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=text('now()'))FastAPI usa la biblioteca Pydantic para validar tanto la solicitud HTTP como el cuerpo de la respuesta HTTP. (Por cierto Pydantic es una biblioteca que le proporcionará la validación de la estructura de datos contra un esquema dado) Para ese propósito, debe crear una clase Pydantic Model que corresponda a su clase Post de sqlalchemy.
Lea los documentos aquí para obtener más información sobre el modelo de respuesta.
FYI, aquí está cómo hacerlo con su ejemplo:
from fastapi import FastAPI, Response, HTTPException from fastapi.params import Body, Depends from sqlalchemy.orm import Session from starlette import status from . import models from .database import engine, get_db from .models import Post from pydantic import BaseModel from datetime import datetime from typing import Dict, List # Define your pydantic response model class PostResponse(BaseModel): id: int title: str content: str published: bool created_at: datetime models.Base.metadata.create_all(bind=engine) app = FastAPI() # Set PostResponse as a response model in the route decorator @app.get("/posts", response_model=Dict[str, List[PostResponse]]) def get_posts(db: Session = Depends(get_db)): posts = db.query(models.Post).all() return {"data": posts} @app.post("/posts", status_code = status.HTTP_201_CREATED, response_model=Dict[str, PostResponse]) def create_posts(post: Post, db: Session = Depends(get_db)): new_post = models.Post(title=post.title, content=post.content, published=post.published) # db.add(new_post) # db.commit() # db.refresh(new_post) return {"data": new_post}EXTRA: También podría estar interesado en la biblioteca SQLModel que es del mismo autor de FastAPI y es una combinación entre SQL Alchemy y la biblioteca Pydantic y básicamente le permite evitar la duplicación (y declarar su modelo solo una vez)