Home > Software engineering >  InValid Pydantic Field Type POST parameters (FastApi) - Python 3.8
InValid Pydantic Field Type POST parameters (FastApi) - Python 3.8

Time:02-02

I am attempting to use FastApi SqlAlchemy And am having an issue with Parameters. This is the Error my Post parameter is causing. What am i doing wrong?

ERROR MESSAGE

fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'app.models.Post'> is a valid pydantic field type

Code

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}

Post Type

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()'))

CodePudding user response:

FastAPI uses Pydantic library to validate both HTTP request and HTTP response body. ( BTW Pydantic is a library that will provide you validation of data structure against a given schema ) For that purpose, you must create a Pydantic Model class that corresponds to your sqlalchemy Post class.

Please read the docs here to learn more about response model.

FYI, here is how to do with your example :

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 : You might be also interested in SQLModel library which is from the same author of FastAPI and is a combination between SQL Alchemy and Pydantic library and basically allow you to avoid duplication (and declare your model only once)

  •  Tags:  
  • Related