FastAPI Response Model via Pydantic

  • There are times where you don't want all the data sent back to the user

  • This is where you would want to define how the response looks like

  • In the schemas.py we will define the Pydantic model for the response

from pydantic import BaseModel

# Note: This file is used to define Pydantic models
# Used for POST and RESPONSE in FastAPI

# The below code handles the user sending data to us
class PostBase(BaseModel):
    title: str
    content: str
    published: bool = True

class PostCreate(PostBase):
    pass

# The below code handles us sending data back to the user
class PostResponse(BaseModel):
    title: str
    content: str
    published: bool
  • This will return only the fields specified in the PostResponse class

  • We will also have to define the response_model in the app decorator

@app.post("/posts", status_code=status.HTTP_201_CREATED, response_model=schemas.PostResponse)
def create_posts(post: schemas.PostCreate, db: Session = Depends(get_db)):

    new_post = models.Post(**post.dict())
    db.add(new_post)
    db.commit()
    db.refresh(new_post)

    return new_post
  • This will still not work fully as our Pydantic model only knows how to work with dictionary's

  • The issue here is that when we make the query, new_post is a SQLAlchemy model

  • Pydantic has no idea what to do with that, so the SQLAlchemy model has to be converted to a Pydantic model

  • More information about this: Click here!

  • To do that we will have to pass the following code

class Config:
        orm_mode = True
  • This will tell Pydantic to convert it, even if it's not a valid dict

  • So the new class in schemas.py should look like this

class PostResponse(BaseModel):
    title: str
    content: str
    published: bool

    class Config:
        orm_mode = True
  • Now this should work and return our correct response

  • When retrieving a list, just passing in the normal decorator parameter schemas.PostResponse will not work

  • We need to convert this to a List with from the typing library

  • How it should look: List[schemas.PostResponse]

@app.get("/posts", response_model=List[schemas.PostResponse])
def get_posts(db: Session = Depends(get_db)):

    posts = db.query(models.Post).all()

    return posts

Last updated