es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Problema con el modelo de SQLAlchemy en FastAPI.

Estoy teniendo problemas con el esquema de mi modelo de SQLAlchemy. Específicamente con este esquema en mi archivo models.py:

from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from .database import Base

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    email = Column(String, unique=True, index=True)    

y este es mi archivo main.py:

from typing import List
from fastapi import Depends, FastAPI, HTTPException,status
from sqlalchemy import schema
from sqlalchemy.orm import Session
import psycopg2
from psycopg2.extras import RealDictCursor
from . import models
from .database import SessionLocal, engine,get_db

models.Base.metadata.create_all(bind=engine)

app = FastAPI()

@app.get("/posts")
def get_post(db: Session=Depends(get_db)):
    posts = db.query(models.User).all()
    return {"data": posts}

@app.post("/posts", status_code=status.HTTP_201_CREATED)
def create_post(post: models.User, db: Session=Depends(get_db)):
    new_post = models.User(title=post.title, email=post.email)
    db.add(new_post)
    db.commit()
    db.refresh(new_post)

    return {"data": new_post}

El error que obtengo de mi aplicación principal es:

fastapi.exceptions.FastAPIError: ¡Argumentos inválidos para el campo de respuesta! Sugerencia: verifica que <class 'app.models.user'=""> sea un tipo de campo pydantic válido.

¿Alguna idea de por qué está sucediendo esto?
PD: Soy nuevo en FastAPI y SQLAlchemy.
Gracias de antemano por su ayuda y apoyo.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El mensaje de error indica que hay un problema con el esquema del modelo de usuario cuando se utiliza como modelo de Pydantic para FastAPI.

    Para resolver este problema, puedes usar la función sqlalchemy_to_pydantic de Pydantic para convertir el modelo SQLAlchemy en un modelo Pydantic. Aquí tienes un ejemplo de cómo usarlo:

    from sqlalchemy.ext.declarative import as_declarative, declared_attr
    from pydantic import BaseModel
    from sqlalchemy.sql import func
    
    
    @as_declarative()
    class Base:
        id = Column(Integer, primary_key=True, index=True)
        created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
        updated_at = Column(DateTime(timezone=True), onupdate=func.now(), nullable=False)
    
        @declared_attr
        def __tablename__(cls):
            return cls.__name__.lower()
    
    
    class User(Base):
        title = Column(String, index=True)
        email = Column(String, unique=True, index=True)
    
    
    # Convertir modelo SQLAlchemy en modelo Pydantic
    class UserOut(BaseModel):
        id: int
        title: str
        email: str
    
    class UserIn(UserOut):
        pass
    

    Luego, en tu archivo main.py, puedes usar los modelos Pydantic UserIn y UserOut:

    from typing import List
    from fastapi import Depends, FastAPI, HTTPException,status
    from sqlalchemy.orm import Session
    import psycopg2
    from psycopg2.extras import RealDictCursor
    from . import models
    from .database import SessionLocal, engine,get_db
    
    
    models.Base.metadata.create_all(bind=engine)
    
    app = FastAPI()
    
    
    @app.get("/posts", response_model=List[models.UserOut])
    def get_post(db: Session=Depends(get_db)):
        posts = db.query(models.User).all()
        return{"data": posts}
    
    
    @app.post("/posts", response_model=models.UserOut, status_code=status.HTTP_201_CREATED)
    def create_post(user: models.UserIn, db: Session=Depends(get_db)):
        new_user = models.User(**user.dict())
        db.add(new_user)
        db.commit()
        db.refresh(new_user)
    
        return{"data": new_user}
    

    Ten en cuenta que estamos usando los modelos Pydantic UserIn y UserOut como los modelos de entrada y salida para el endpoint /posts, y también especificamos el parámetro response_model en el endpoint get_post para indicarle a FastAPI qué tipo de datos se está devolviendo.

Comments are closed.