Refactorización y Modularización

Response Model

Es un atributo de nuestro path operation el cual es llamado desde nuestro Path Operation Decorator, el cual es utilizado para evitar el filtrado de información sensible, en este definiremos un nuevo modelo que será el que se usará para el Response, por ejemplo si una persona realiza un POST con su contraseña en él, no podemos enviar la contraseña de regreso en el Response, esto sería un problema de seguridad bastante fuerte, entonces teniendo el modelo Person

Modelo Person Original

# Python
from typing import Optional

# Pydantic
from pydantic import BaseModel
from pydantic import Field, EmailStr

class Person(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example='John',
    )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example='Doe',
    )
    age: int = Field(
        ...,
        gt=0,
        le=110,
        example=25,
    )
    hair_color: Optional[HairColor] = Field(
        default=None,
        example=HairColor.blonde,
    )
    is_married: Optional[bool] = Field(
        default=None,
        example=False
    )
    email = EmailStr()

    password: str = Field(
        ...,
        min_length=8,
        max_length=50,
        example='password'
    )

Modelo PersonOut

Este es el modelo que se enviara por medio del Response

class PersonOut(BaseModel):
    first_name: str
    last_name: str
    age: int
    hair_color: Optional[HairColor]
    is_married: Optional[bool]
    email: EmailStr

Añadir el modelo en el Path Operation Decorator

@app.post('/person/new', response_model=PersonOut)
def create_person(person: Person = Body(...)):
    return person

Se añade el modelo modificado para el response dentro del Path Operation Decorator en el parametro Response Model

Mejorando la calidad del código: eliminando líneas duplicadas

Aunque que hicimos anteriormente funciona técnicamente no es la forma mas optima de trabajar nuestros modelos, lo que deberiamos hacer es generar una modelo base como PersonBase y hacer que de allí hereden Person y PersonOut

Modelos Mejorados

class PersonBase(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example='John',
    )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example='Doe',
    )
    age: int = Field(
        ...,
        gt=0,
        le=110,
        example=25,
    )
    hair_color: Optional[HairColor] = Field(
        default=None,
        example=HairColor.blonde,
    )
    is_married: Optional[bool] = Field(
        default=None,
        example=False
    )
    email = EmailStr()

    class Config:
        schema_extra = {
            "example": {
                'first_name': 'Edkar',
                'last_name': 'Chachati',
                'age': 20,
                'hair_color': HairColor.black,
                'is_married': False
            }
        }

class Person(PersonBase):
    password: str = Field(
        ...,
        min_length=8,
        max_length=50,
        example='password'
    )

class PersonOut(PersonBase):
    pass

Status Code personalizados

Manejo de Errores en un Servicio REST

Para añadir los status code dentro de FastAPI funciona muy similar a añadir un Response Model en el Path Operation Decoractor usando el parametro status_code

@app.get(
    path='/',
    status_code=status.HTTP_200_OK
)
def home():
    return {'hello': 'world'}

@app.post(
    path='/person/new',
    response_model=PersonOut,
    status_code=status.HTTP_201_CREATED
)
def create_person(person: Person = Body(...)):
    """
    Rescata mi documentacion mardita pvta
    """
    return person