Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Creando ejemplos de Request Body automáticos

18/20
Recursos

Aportes 54

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Buena noche amigos

despues de hacer unas pruebas, me di cuenta que no es necesario quitar el doble RequestBody, el unico requisito para que funcione, es que el Dict de prueba se llame ‘example’

class Config:
        schema_extra = {
            "example": {
                "first_name": "Rodrigo",
                "last_name": "Lopez",
                "age": 30,
                "hair_color": "black",
                "is_married": False
            }
        }

O bien tambien pueden agregar la propieda example dentro de cada atributo de la case e igual funcionara!

Super, nunca había utilizado esta característica de fastAPI !!!
De verdad que muchas gracias por los conceptos transmitidos.

De hecho no es necesario modificar la función para que solo lea un request body, se puede con ambas, el único requisito es que la instancia a agregar en cada clase se llame “example” :

#Person model
class Person(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        )
    age: int = Field(
        ...,
        gt=0,
        le=115
    )
    email : EmailStr = Field(...)
    website: HttpUrl = Field(default=None)
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)

    class Config:
        schema_extra = {
            "example" : {
                "first_name" : "Fulano",
                "last_name" : "Pérez",
                "age" : "40",
                "email" : "[email protected]",
                "website" : "https://www.live.com",
                "hair_color" : "black",
                "is_married" : True
            }
        }

#Location model
class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=2,
        max_length=100
        )
    state: str = Field(
        ...,
        min_length=2,
        max_length=100
        )
    country: str = Field(
        ...,
        min_length=2,
        max_length=100
        )
    class Config:
        schema_extra = {
            "example" : {
                "city" : "San Francisco",
                "state" : "California",
                "country" : "USA"
            }
        }

Mi aporte al reto:
![](

Asi me quedo el Location con examples:

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Cuernavaca"
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Morelos"
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Mexico"
    )

Les dejo mas documentacion util hablando sobre este tema en particular! schema-extra-example

Reto:

class Location(BaseModel):
    city: str = Field(
        ...,
        title="City",
        description=None,
        min_length=1,
        max_length=50,
        example="Lima"
    )
    state: str = Field(
        ...,
        title="State",
        description=None,
        min_length=1,
        max_length=50,
        example="Lima"
    )
    country: str = Field(
        ...,
        title="Country",
        description=None,
        min_length=1,
        max_length=50,
        example="Peru"
    ) 
class Location(BaseModel):
    city: str = Field(
        ..., 
        min_length= 1,
        max_length= 115,
        example = "Barranquilla"
        )
    state: str = Field(
        ..., 
        min_length= 1,
        max_length= 115,
        example = "Atlantico"
        )
    country: str = Field(
        ..., 
        min_length= 1,
        max_length= 115,
        example = "Colombia"
        )
class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=100,
        example='Caracas city'
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=180,
        example='Caracas'
    )
    country: Countries = Field(
        ...,
        example='venezuela'
    )

    class Config:
        schema_extra = {
            'example': {
                'city': 'caracas',
                'state': 'distrito capital',
                'country': 'venezuela'
            }
        }
<class LocationExample(Enum):
    city = "Ensenada"
    state = "Baja"
    country = "Mexico"

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example=LocationExample.city
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example=LocationExample.state
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example=LocationExample.country
    )> 

No se si fue por una actualización o cual sera el motivo, pero a mi si me permite ponerle datos de ejemplo al hair_color.

    hair_color: Optional[HairColor] = Field(
        default=None,
        example="brown"
        )

Aquí está mi reto que funciona perfectamente en Swagger:

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=20,
        example="Eclhe"
    )

    state: str = Field(
        ...,
        min_length=1,
        max_length=20,
        example="Alicante"
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=20,
        example="Spain"
    )

**Hola!, Mi solución
**

    #python
from typing import Optional
from enum import Enum
from datetime import date


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


    #fastAPI
from fastapi import FastAPI
from fastapi import Body, Query, Path


app = FastAPI()

    #Models

class Card(BaseModel):
    name: str = Field(..., min_length= 1, max_length= 50)
    number: PaymentCardNumber
    exp: date


class HairColor(Enum):
    white = "white"
    brown = "brown"
    black = "black"
    blonde = "blonde"
    red = "red"


class Location(BaseModel):
    city: str = Field(..., min_length= 3, max_length= 20, example= "Bogotá")
    state: str = Field(..., min_length= 3, max_length= 20, example= "Bogotá D.C")
    country: str = Field(..., min_length= 3, max_length= 20, example= "Colombia")


class Person(BaseModel):
    first_name: str = Field(..., min_length= 1, max_length= 50, example= "Facundo")
    last_name: str = Field(..., min_length= 1, max_length= 50, example= "García Martoni")
    age: int = Field(..., gt= 0, le=115, example= 21)
    email: EmailStr = Field(...)
    card: Optional[Card] = Field(default=None, example ={"name": "Facundo García", "number": "4000000000000002", "exp": date(2022,4,21)})
    hair_color: Optional[HairColor] =  Field(default= None, example= "blonde")
    is_married: Optional[bool] = Field(default= None, example= False)


@app.get("/")
def home():
    return {"Hello": "World"}


    #Request and Response Body

@app.post("/person/new")
def create_person(person: Person = Body(...)):
    return person


    #validaciones: Query Parameters
    
@app.get("/person/detail")
def show_person( name: Optional[str] = Query(None,
                                             min_length=1,
                                             max_length=50,
                                             title="Person Name",
                                             description="This is the person name. It's between 1 and 50 charaters"),
                age: Optional[int] = Query(..., 
                                           title="Person Age",
                                           description=" This is de person age. It's required"                    
                                           )
                ):
    return {name: age}


    #validaciones: Path Parameters
    
@app.get("/person/detail/{person_id}")
def show_person(person_id: int = Path(...,
                                      gt=0,
                                      title="Person Id",
                                      description="This is the Person id. It's requered")):
    return {person_id: "It exists!"}


    #validaciones: Request Body
    
@app.put("/person/{person_id}")
def update_person(person_id: int = Path(...,
                                       title="Person Id",
                                       description="This is the person ID",
                                       gt=0),
                  person: Person = Body(...),
                  location: Location = Body(...)
                  ):
    results = person.dict()
    results.update(location.dict())
    return results

Resultados:

Método fácil

class Location(BaseModel):
    city: str = Field(
        ...,
        example="Medellín"
    )
    state: str = Field(
        ...,
        example="Antioquia"
    )
    country: str = Field(
        ...,
        example="Colombia"
    )

# Path operation

@app.put("/person/details/{person_id}")
def update_location(
    person_id: int = Path(
        ...,
        title="Person id",
        description="This is the person id",
        gt=0
    ),
    location: Location = Body(
        ...,
        title="Current person's location",
        description="Update the actual location of the person"
    )

):
    return location

Creo que para esta fecha Si funciona tengo unas cosas agregadas pero me fuinciona

# Python : está por encima de cualquier librería, así que todo lo que sea de python va encima
from datetime import date
from typing import Any, Optional # Sirve para definir tipos de datos en python y volver a python como un lenguaje de programación estatico
from enum import Enum # Sirve para definir enumeraciones en python de strings

#Pydantic : Esta librería esta por encima de FastAPI, es decir que FastAPI lo utiliza, por ello se pone por encima (jerarquía)
from pydantic import BaseModel, EmailStr, FutureDate   # Sirve para definir los modelos de datos que se usaran en la aplicacion
from pydantic import Field, PositiveInt, HttpUrl
from pydantic.types import PaymentCardBrand, PaymentCardNumber, constr

# FastAPI
from fastapi import FastAPI  # Sirve para definir la API de la aplicacion
from fastapi import Body, Query, Path # Sirve para definir el tipo de dato que se usara en la API

app = FastAPI()

# Models

class HairColor(Enum):
    RED = "red"
    BLOND = "blond"
    BROWN = "brown" 
    BLACK = "black"

class Location(BaseModel):
    city: str = Field(
        ...,
        title = "Ciudad",
        description = "City",
        min_length = 3,
        max_length= 35
    )
    country: str = Field(
        ...,
        title = "country",
        description = "descricion de ciudad",
        min_length = 3,
        max_length = 100
    )
    state: str = Field(
        ...,
        title = "Estado",
        description = "Nombre del Estado",
        min_length = 3,
        max_length = 50
    )
    lat: float = Field(
        ...,
        title = "latitud",
        description = "Descripcion de la Latitud"

    )
    lon: float = Field(
        ...,
        title = "Longitud",
        description = "Descricion de la Longitud"
    )
        
    
class Person(BaseModel): # Sirve para definir los modelos de datos que se usaran en la aplicacion
    first_name: str = Field(...,
    title = "First Name",
    description = "The person's first name",
    max_length = 50,
    min_length = 2 ) # Field sirve para definir los campos que se usaran en la aplicacion
    
    last_name: str = Field(
        ...,
        title = "Last Name",
        description = "The person's last name",
        max_length = 50,
        min_length = 2 )
    
    age: int = Field(
        ...,
        title = "Age",
        description = "The person's age",
        gt = 0,
        lt = 100 )
    
    email: EmailStr = Field(
        ...,
        title = "Email",
        description = "Email de Persona"
        
    )
    
    hair_color: Optional[HairColor] = Field(default = None)
    
    is_married: Optional[bool] = Field(default = None)

    vali_card: Optional[FutureDate] = Field(...)
    phone_number:Optional[PositiveInt] = Field(defaul = None)
    name_person: constr(strip_whitespace=True, min_length=1)
    number: Optional[PaymentCardNumber] = Field(default = None)
    exp: date
    web: Optional[HttpUrl] = Field(default = None)

    class Config:
        schema_extra = {
            "example": {
                "first_name": "Jesus Enrique",
                "last_name": "Morocoima Marcano",
                "age": "34",
                "hair_color": "black",
                "is_married": False
            }
        }

     
@app.get("/")
def home(): # Sirve para definir la ruta de la API
    return {"message": "Hello World"}

# Requests and responses Body

@app.post("/person/new") 
def create_person(person: Person = Body(...)): # Sirve para definir el tipo de dato que se usara en la API
    return person

# Validaciones; Query Parametros

@app.get("/person/detail")
def show_person(
    person_id: int = Query(
        ...,
        gt = 0,
        lt = 100000000,
        title = "Id de la persona",
        description = "Id de la persona a consultar y es un parametro requerido"

        ), # Sirve para definir el tipo de dato que se usara en la API
    first_name: str = Query(
        ...,
        min_length = 1,
        max_length = 50,
        title = "Nombre de la Persona",
        description = " Este es el nombre de la persona como minimo 1 a 50 caracteres"

        ), # Sirve para definir el tipo de dato que se usara en la API
    last_name: str = Query(
        ...,
        min_length = 1,
        max_length = 50,
        title = "Apellido de la Persona",
        description = " Este es el apellido de la persona como minimo 1 a 50 caracteres"

        ), # Sirve para definir el tipo de dato que se usara en la API
        
    age: int = Query(
        ...,
        gt = 0,
        lt = 100,
        title = "Edad de la Persona",
        description = " Este es la edad de la persona y es un paramtero requerido"
        
        ), # Sirve para definir el tipo de dato que se usara en la API
        
    hair_color: Optional[str] = Query(
        None,
        min_length = 3,
        max_length = 50,
        title = "Color de pelo de la Persona",
        description = " Este es el color de pelo de la persona como minimo 3 a 50 caracteres"
        ),

    is_married: Optional[bool] = Query(
        None,
        title = "Estado civil de la Persona",
        description = " Este es el estado civil de la persona Treu Si esta Casada, Fals Si no esta Casada"
        )
):
    return {
        "person_id": person_id,
        "first_name": first_name,
        "last_name": last_name,
        "age": age,
        "hair_color": hair_color,
        "is_married": is_married
    }

# Valadaciones: Pach Parametros

@app.get("/person/detail/{person_id}/{first_name}/{last_name}")
def show_person(
    person_id: int = Path(
        ...,
        gt = 0,
        lt = 100000000,
        title = "Id de la persona",
        description = "Id de la persona a consultar y es un parametro requerido"
        ), # Sirve para definir el tipo de dato que se usara en la API
    
    first_name: str = Query(
        ...,
        min_length = 1,
        max_length = 50,
        title = "Nombre de la Persona",
        description = " Este es el nombre de la persona como minimo 1 a 50 caracteres"
        ), # Sirve para definir el tipo de dato que se usara en la API

    last_name: str = Query(
        ...,
        min_length = 1,
        max_length = 50,
        title = "Apellido de la Persona",
        description =" Este es el apellido de la persona como minimo 1 a 50 caracteres"
        ),

    age: int = Query(
        ...,
        gt = 0,
        lt = 100,
        title = "Edad de la Persona",
        description = " Este es la edad de la persona y es un paramtero requerido"
        ),

    hair_color: Optional[str] = Query(
        None,
        min_length = 3,
        max_length = 50,
        title = "Color de pelo de la Persona",
        description = " Este es el color de pelo de la persona como minimo 3 a 50 caracteres"
        ),

    is_married: Optional[bool] = Query(
        None,
        title = "Estado civil de la Persona",
        description = " Este es el estado civil de la persona"
        ),
):
    return {
        "person_id": person_id,
        "first_name": first_name,
        "last_name": last_name,
        "age": age,
        "hair_color": hair_color,
        "is_married": is_married
    }

#  Valadaciones: Body Parametros 

@app.put("/person/{person_id}")
def update_person(
    person_id: int = Path(
        ...,
        gt = 0,
        lt = 10000000,
        title = "Id de la persona",
        description = "Id de la persona a consultar y es un parametro requerido"
        ), # Sirve para definir el tipo de dato que se usara en la API

    person: Person = Body(...,
    title = "Persona a actualizar",
    description = "Persona a actualizar"
    ),

    location: Location = Body(
        ...,
        title = "Ubicacion de la persona",
        description = "Ubicacion de la persona"
        )
       
):
    result = person.dict()
    result.update(location.dict())
    return result

Para que la documentación pueda reconocer la enumeración de la clase HairColor, colóquenlo de la siguiente forma:

class Config:
        schema_extra = {
            "example": {
                "first_name": "Miguel",
                "last_name": "Torres",
                "age": "25",
                "hair_color": HairColor['black'],
                "is_married": False
            }
        }

Decidi implementar la primera forma

#Python
from typing import Optional
from enum import Enum

#Pydantic
from pydantic import BaseModel, PaymentCardNumber
from pydantic import Field, EmailStr, PositiveInt, HttpUrl

#FastAPI
from fastapi import FastAPI
from fastapi import Body, Query, Path


app = FastAPI()


#Models
class HairColor(Enum):
    white = 'white'
    brown = 'brown'
    black = 'black'
    blonde = 'blonde'
    red = 'red'

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=30
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=30
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=30
    )

    class Config:
        schema_extra = {
            'example': {
                'city': 'Coronel Suarez',
                'state': 'Provincia de Buenos Aires',
                'country': 'Argentina'
            }
        }

class Person(BaseModel):
    first_name: str = Field(
        ..., 
        min_length=1,
        max_length=50
    )
    last_name: str = Field(
        ..., 
        min_length=1,
        max_length=50
    )
    age: int = Field(
        ...,
        gt=0,
        lt=115
    )
    email: EmailStr = Field(...)
    payment_card: Optional[PaymentCardNumber] = Field(default=None)
    personal_page: Optional[HttpUrl] = Field(default=None)
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)

    class Config:
        schema_extra = {
            'example': {
                'first_name': 'Manuel',
                'last_name': 'Ducos',
                'age': 16,
                'email': '[email protected]',
                "payment_card": "0000000000000000",
                "personal_page": "https://google.com",
                "hair_color": "brown",
                "is_married": False
            }
        }

@app.get('/')
def home():
    return {'Hello': 'World'}


# Request and Response body
@app.post('/person/new')
def create_person(person: Person = Body(...)):
    return person


# Validaciones: Query parameters
@app.get('/person/detail')
def show_person(
    name: Optional[str] = Query(
        None,
        min_length=1,
        max_length=50,
        title='Person Name',
        description='This is the person name. It\'s between 1 and 50 characters'
        ),
    age: str = Query(
        ...,
        title='Person Age',
        description='This is the person age. It\'s required'
        )
):
    return {name: age}


# Validaciones: Path parameters
@app.get('/person/detail/{person_id}')
def show_person(
    person_id: int = Path(
        ..., 
        gt=0,
        title='Person Age',
        description='This is the peron age. It\'s required'
        )
):
    return {person_id: 'It exists!'}


# Validaciones: Request Body
@app.put('/person/{person_id}')
def update_person(
    person_id: int = Path(
        ...,
        title='Person ID',
        description='This is the person ID',
        gt=0
    ),
    person: Person = Body(...),
    location: Location = Body(...)
):
    results = person.dict()
    results.update(location.dict())
    return results

Se logró ✨

Para no borrar lo anterior se puede agregar otro endpoint

# Validate: Request body
@app.put('/person/{person_id}')
def update_person(
        person_id: int = Path(
            ...,
            title='Person ID',
            description='This is the person ID',
            gt=0
        ),
        person: Person = Body(...),
):
    """Update a person."""
    return person


# Validate: Request body
@app.put('/person-location/{person_id}')
def update_person_location(
        person_id: int = Path(
            ...,
            title='Person and location',
            description='Update a person a location',
            gt=0
        ),
        person: Person = Body(...),
        location: Location = Body(...)
):
    """Update a person."""
    results = person.dict()
    results.update(location.dict())
    return results

Aporte del reto:

Clase

class Location(BaseModel): 
    city: str = Field(
        ...,
        min_length=1,
        max_length=30,
        title="City of the person"
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=30,
        title="State of the person"
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=30,
        title="Country of the person"
    )

    class Config: 
        schema_extra = {
            "example": {
                "city": "El Tigre",
                "state": "Anzoategui",
                "country": "Venezuela" 
                
            }
        }

Request and Response Body Location

@app.post("/location/new")
def create_location(location: Location = Body(...)): 
    return location

pues utilice la example

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=2,
        max_length=50,
        example='Guadalajara',
    )
    state: str = Field(
        ...,
        min_length=2,
        max_length=50,
        example='Jalisco',
    )
    country: str= Field(
        ...,
        min_length=2,
        max_length=50,
        example='México',
    )

Challenge

# Python
from typing import Optional, List
from enum import Enum
from datetime import date

# Pydantic
from pydantic import BaseModel
from pydantic import Field, EmailStr
from pydantic.color import Color
from pydantic.types import PaymentCardBrand, PaymentCardNumber, constr

# FastAPI
from fastapi import FastAPI
from fastapi import Body, Query, Path # specified the parameter have a body

# this var contain all the app
app = FastAPI()

# Models

class HairColor(Enum):
    white: Color= "#FFFFFF"
    brown: Color= "#964B00"
    black: Color= "#282c34"
    blonde: Color= "#f5e265"
    red: Color= "#c11b1b"


class Location(BaseModel):
    city: str = Field(
        ..., 
        min_length=1,
        max_length=50,
    )
    state: str = Field(
        ..., 
        min_length=1,
        max_length=50,
    )
    country: str = Field(
        ..., 
        min_length=1,
        max_length=50,
    )

    class Config:
        schema_extra = {
            "example": {
                "city": "Bogotá",
                "state": "Some place",
                "country": "MEX",
            }
        }


class Person(BaseModel):
    first_name: str = Field(
        ..., 
        min_length=1,
        max_length=50,
        example="Greg"
    )
    last_name: str = Field(
        ..., 
        min_length=1,
        max_length=50,
        example="Mur",
    )
    age: int = Field(
        ..., 
        gt=0,
        le=115
    )
    email: List[EmailStr]
    # if the user dont send nothing the value is NULL
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)

    class Config:
        schema_extra = {
            "example": {
                "first_name": "Nate",
                "last_name": "Al",
                "age": 33,
                "email": ["[email protected]"],
                "hair_color": "#964B00",
                "is_married": False,
            }
        }


class Card(BaseModel):
    name: constr(strip_whitespace=True, min_length=1)
    number: PaymentCardNumber = Field(
        ..., 
        min_length=1,
        max_length=16,
    )
    exp: date = Field(
        ..., 
        title="Expired date",
        description="This is the expired date for the card",
    )


    @property
    def brand(self) -> PaymentCardBrand:
        return self.number.brand

    @property
    def expired(self) -> bool:
        return self.exp < date.today() 
        
    
    class Config:
        schema_extra = {
            "example": {
                "name": "NATE",
                "number": 1234567890123456,
                "exp": date.today(),
            }
        }



# Fast operations
@app.get("/") # path operation decorator
def home(): # path operation function
    return {"Hello": "World"}

# Request and response body
@app.post("/person/new")
def create_person(person: Person = Body(...)):
    return person

# Validations: Query params
@app.get("/person/detail")
def show_person(
    name: Optional[str] = Query(
        None, 
        min_length=1, 
        max_length=50,
        title="Person name",
        description="This is the person name. It's between 1 and 50 characters",
    ),
    age: str = Query(
        ...,
        title="Person age",
        description="This is the person age. It's required",
    ),
):
    return {name: age}

# Validations: Path params
@app.get("/person/detail/{person_id}")
def show_person(
    person_id: int = Path(
        ..., 
        gt=0,
        title="Person id",
        description="This is the person id. It's required",
    )
):
    return {person_id: "It exists!"}

# Validations: Request body
@app.put("/person/{person_id}")
def update_person(
    person_id: int = Path(
        ...,
        title= "Person ID",
        description= "This is the person id.",
        gt= 0,
    ),
    person: Person = Body(...),
    location: Location = Body(...),
    card: Card = Body(...),
): 
    results = person.dict()
    results.update(location.dict()) # append the dic
    results.update(card.dict())
    return results
#Python
from typing import Optional
from enum import Enum

#Pydantyc
from pydantic import BaseModel
from pydantic import Field
from pydantic import EmailStr

#FastAPI
from fastapi import FastAPI
from fastapi import Body,Query,Path # Body: me permite especificar que un parametro que esta llegando es de tipo body, el ... quiere decir que el parametro oatributo es obligatorio

app=FastAPI()

#Models
class HairColors(Enum):
    white="White"
    black="Black"
    brown="Brown"
    blonde="Blonde"
    red="Red"

class Paises(Enum):
    colombia="Colombia"
    venezulela="Venezuela"
    panama="Panama"
    ecuador="Ecuador"
    peru="Peru"
    brasil="Brasil"
    chile="Chile"
    paraguay="Paraguay"
    uruguay="Uruguay"
    argentina="Argentina"


class Location(BaseModel):
    city:str=Field(
        ...,
        min_length=4,
        max_length=30,
        #example="Cartagena"
    )
    state:str=Field(
        ...,
        min_length=4,
        max_length=30,
        #example="Bolivar"
    )
    country:Paises=Field(
        ...,
        #example="Colombia"
        )
    class Config:
        schema_extra={
            "example":{
                "city":"Cartagena D.T y C",
                "state":"Bolivar",
                "country":"Colombia"
            }
        }


class Person(BaseModel):
    first_name:str=Field(
        ...,
        min_length=1,
        max_length=50,
        example="Neyla del Carmen"
        )
    last_name:str=Field(
        ...,
        min_length=1,
        max_length=50,
        example="Polo"
    )
    age:int=Field(
        ...,
        gt=0,
        le=115,
        example=32
    )
    email:EmailStr=Field(
        ...,
        example="[email protected]")
    hair_color:Optional[HairColors]=Field(default=None,example="White")
    is_married:Optional[bool]=Field(default=None,example=False)

    #Creando ejemplos de Request Body automáticos
    """class Config:
        schema_extra={
            "example":{
                "first_name":"Neyla",
                "last_name":"Polo",
                "age":32,
                "hair_color":"Black",
                "is_married":True,
                "email":"[email protected]"

            }
        }
    """
@app.get("/")
def  home():
    return {
        "Hello":"World"
    }
#Request and Response Body

@app.post("/person/new")
def create_person(person:Person=Body(...)):
    return person
    
#Validaciones: Query Parameters
@app.get("/person/detail")
def show_person(  
    name:Optional[str]=Query(
        None,
        min_length=1,
        max_length=50,
        title="Person Name",
        description="This is the person name. It's between 1 and 50 characters "
    ),
age:str=Query(
    ...,
    title="Person Age",
    description="This is the person age, it's required"
    )
):
    return  {name:age}


#Validaciones path parameters
@app.get("/person/detail/{person_id}")
def show_person(
    person_id:int=Path(
        ...,
        gt=0,
        title="Person Id",
        description="It's the person id, It's required"
        )
):
    return {person_id:"It Exits!"}

#Validaciones: Request body
@app.put("/person/{person_id}")
def update_person(
    person_id:int=Path(
        ...,
        gt=0,
        title="Person Id",
        description="This is the person if, It's greater than 0"
    ),

    person:Person=Body(...),
    location:Location=Body(...)
    
):
    result = person.dict()
    result.update(location.dict())
    return result

Hola, aqui dejo la validacion con ejemplos de ambas formas, deje comentado la primera forma que explico Facundo

class Location(BaseModel):
    city: str = Field(
        min_length=3,
        max_length=20,
        title="City",
        description="This is the city of the person",
        example="Ciudad de Buenos Aires"

    )
    state: str = Field(
        min_length=3,
        max_length=20,
        title="State",
        description="This is the State of the City",
        example="Buenos Aires"
    )
    country: str =Field(
        min_length=3,
        max_length=20,
        title="Country",
        description="This is the Country",
        example="Argentina"
    )
    """
    class Config:
            schema_extra = {
                "example": {
                    "city": "San Antonio de los Altos",
                    "state": "Miranda",
                    "country": "Venezuela",
                    
                }
            }
    """
    ```

Código:

Resultado:

Esta es misolucion al reto

class Config:
        schema_extra = {
            "example": {
                "city": "Tunja",
                "state": "Boyaca",
                "country": "Colombia"
            }
        }

Tiene razón no soporta los enum todavía

Aquí mi modificación de Location, se aprende mucho con este curso

class Location(BaseModel):
    city: str = Field(..., max_length=30, min_length=2)
    state: Optional[str] = Field(max_length=30, min_length=2)
    country: str = Field(..., max_length=30, min_length=2)

    class Config:
        schema_extra={
            "example":{
                "city" : "Buga",
                "state": "Valle",
                "country": "ur sister's p*ssy"
            }
        }

Código reto relleno automático de la clase Location para Swagger.

class Location(BaseModel):
    city: str = Field(example="València")
    state: str = Field(example="València")
    country: str = Field(example="Spain")
    class Config:
        schema_extra = {
            'example': {
                'first_name': 'Facundo',
                'last_name': 'García Martoni',
                'age': 21,
                'hair_color': 'blond',
                'is_married': False,
                'email': 'facundo@gmail.com',
                'web_page': 'https://facundo.com.co',
                'height': 160.5
            }
        }
class Location(BaseModel):
    city: str = Field(
	min_length=1,
        max_length=50,
        example='Coatzacoalcos'
    )
    state: str = Field(
        min_length=1,
        max_length=50,
        example='Veracruz'
    )
    country: str = Field(
        min_length='1',
        max_length='50',
        example='México'

    )

Reto completo de las dos maneras:

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=4,
        max_length=24,
        example="Montevideo"
        )
    state: str = Field(
        ...,
        min_length=4,
        max_length=24,
        example="Montevideo"
        )
    country: str = Field(
        ...,
        min_length=4,
        max_length=24,
        example="Uruguay"
        )
    latam: bool = Field(example=True)
    # class Config_loc:
    #     schema_example={
    #         "example": {
    #             "city": "Montevideo",
    #             "state": "Montevideo",
    #             "country": "Uruguay",
    #             "latam": True
    #         }
    #     }

Es importante aclarar que con la etiqueta “example” se pueden mandar más de un request en simultaneo:

colocando:

class Config:
        schema_extra = {
            "example": {
                "first_name": "Luis",
                "last_name": "Perez",
                "age": 30,
                "hair_color": "black",
                "is_married": False
            }
        }

Con la llave: “example” si puedes imprimir los 2 request body

Creando ejemplos de Request Body automáticos

Podemos poner valores por defecto los body parameters. Debemos crear una clase dentro de nuestra clase.

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=75
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=75
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=75
    )

    class Config:
        schema_extra = {
            "example": {
                "city": "Los Angeles",
                "state": "California",
                "country": "USA"
            }
        }


class Person(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50
    )
    last_name: str= Field(
        ...,
        min_length=1,
        max_length=50
    )
    age: int = Field(
        ...,
        gt=0,
        le=115
    )
    hair_color: Optional[HairColor] = Field(default=None, example="brown")
    is_married: Optional[bool] = Field(default=None, example=False)
    email: EmailStr = Field(
        ...,
        title="Email",
        description="Email of the person. Must be valid."
    )
    payment_card_number: PaymentCardNumber = Field(
        ...,
        title="Payment card number",
        description="Payment card number of the person to pay our services. Must be valid."
    )
    favorite_color: Optional[Color] = Field(default=None)

    class Config:
        schema_extra = {
            "example": {
                "first_name": "Miguel",
                "last_name": "Reyes",
                "age": 23,
                "hair_color": "brown",
                "is_married": False,
                "email": "[email protected]",
                "payment_card_number": "5428614385158093"
            }
        }

Y tendremos un JSON con valores por defecto:

{
  "person": {
    "first_name": "Miguel",
    "last_name": "Reyes",
    "age": 23,
    "hair_color": "brown",
    "is_married": false,
    "email": "[email protected]",
    "payment_card_number": "5428614385158093"
  },
  "location": {
    "city": "Los Angeles",
    "state": "California",
    "country": "USA"
  }
}
    class Config:
        schema_extra = {
            "example" : {
                "city": "Imperial",
                "state": "Cañete",
                "country": "Perú"
                
            }
        

Reto

Input code

Output

Mi validación en la clase Location


class Location(BaseModel):
  city: str = Field(
    ...,
    min_length=1,
    max_length=50,
    example="Quito"

  )
  state: str = Field(
    ...,
    min_length=1,
    max_length=50,
    example="Pichincha"
  )
  country: str = Field(
    ...,
    min_length=1,
    max_length=50,
    example="Ecuador"
  )

Buenas, comparto mi código en un pastebin. Ahora pego capturas del resultado de los ejemplos automáticos.

Pastebin de Request Body Examples

Un saludo y gracias.

A practicar mucho

Excelente Clase!!

Reto cumplido!!!

Nota

Aunque aún se sigue teniendo problemas con la clase Enum para poder añadir ejemplo sin la clase config, ahora ya se puede enviar 2 request body.

# Python
from typing import Optional
from enum import Enum

# Pydantic
from pydantic import BaseModel
from pydantic import Field

# FastAPI
from fastapi import FastAPI
from fastapi import Body, Query, Path

app = FastAPI()

# Models
class HairColor(Enum):
    white = "white"
    brown = "brown"
    black = "black"
    yellow = "blonde"
    red = "red"

class Location(BaseModel):
    city: str = Field(default=None)
    state: str = Field(default=None)
    country: str = Field(...)

    class Config:
        schema_extra = {
            "example": {
                "city": "Trujillo",
                "state": "La Libertad",
                "country": "Perú"
            }
        }

class Person(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Miguel"
    )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Torres"
    )
    age: int = Field(
        ...,
        gt=0,
        le=115,
        example=23
    )
    hair_color: Optional[HairColor] = Field(default=None, example="red")
    is_married: Optional[bool] = Field(default=None, example=True)

@app.get("/")
def home():
    return {"Hello": "World"}

# Request and Response Body
@app.post("/person/new")
def create_person(person: Person = Body(...)):
    return person

# Validations: Query Parameters
@app.get("/person/detail")
def show_person(
    name: Optional[str] = Query(
        None,
        min_length=1,
        max_length=50,
        title="Person Name",
        description="This is the person name. It's between 1 and 50 characters"
    ),
    age: str = Query(
        ...,
        title="Person Age",
        description="This is the person age. It's required"
    )
):
    return {name: age}

# Validations: Path Parameters
@app.get("/person/detail/{person_id}")
def show_person(
    person_id: int = Path(
        ...,
        gt=0,
        title="Person ID",
        description="This is the person ID. It's required"
    )
):
    return {person_id: "It exists!"}

# Validations: Request Body
@app.put("/person/{person_id}")
def update_person(
    person_id: int = Path(
        ...,
        title="Person ID",
        description="This is the person ID",
        gt=0
    ),
    person: Person = Body(...),
    location: Location = Body(...)
):
    return person.dict() | location.dict()

#Python
from typing import Optional
from enum import Enum

#Pydantic
from pydantic import BaseModel
from pydantic import Field
from pydantic.networks import EmailStr

#FastAPI
from fastapi import FastAPI
from fastapi import Body, Query, Path

app = FastAPI()

Models

class HairColor(Enum):
white = "white"
brown = "brown"
black = "black"
blonde = "blonde"
red = “red”

class Location(BaseModel):
city: str = Field(
…,
min_length=1,
max_length=50,
example=“Puerto Montt”
)
state: str = Field(
…,
min_length=1,
max_length=50,
example=“Los Lagos”
)
country: str = Field(
…,
min_length=1,
max_length=50,
example=“Chile”
)

class Person(BaseModel):
first_name: str = Field(
…,
min_length=1,
max_length=50,
example=“Giocrisrai”
)
last_name: str = Field(
…,
min_length=1,
max_length=50,
example=“Godoy”
)
age: int = Field(
…,
gt=0,
le=115,
example=30
)
hair_color: Optional[HairColor] = Field(
default=None,
example=HairColor.black
)
is_married: Optional[bool] = Field(
default=None
)
email:str = EmailStr(

)

#class Config:
#    schema_extra = {
#        "example": {
#            "first_name": "Giocrisrai",
#            "last_name": "Godoy Bonillo",
#            "age": 30,
#            "hair_color": "black",
#            "is_married": False,
#            "email": "[email protected]"
#        }
#    }

@app.get("/")
def home():
return {“Hello”: “World”}

Request and Response Body

@app.post("/person/new")
def create_person(person: Person = Body(…)):
return person

Validations: Query Parameters

@app.get("/person/detail")
def show_person(
name: Optional[str] = Query(
None,
min_Length=1,
max_Length=50,
title=“Person Name”,
description=“This is the person name. It’s between 1 and 50 characters”
),
age: str = Query(
…,
title=“Person Age”,
description=“This is the person age. It’s required”
)
):
return {name: age}

Validations : Path Parameters

@app.get("/person/detail/{person_id}")
def show_person(
person_id: int = Path (
…,
gt=0,
title=“Person Id”,
description=“This is the person Id. It’s required and greater than 0”
)
):
return {person_id: “It exists!”}

Validations: Request Body

@app.put("/person/{person_id}")
def update_person(
person_id: int = Path(
…,
title=“Person ID”,
description=“This is the personID”,
gt=0
),
person: Person = Body(…),
#Location: Location = Body(…)
):
#results = person.dict()
#results.update(Location.dict())
#return results
return person

Reto

class Location(BaseModel):
    Longitud: float = Field(...,ge=-90.000,le=90.000)
    Latitud: float = Field(...,ge=-90.000,le=90.000)
    class Config:
        schema_extra={
            "example":{
                "Longitud":56.21984,
                "Latitud":2.5656,
            }
        }

listo n.n

class Location(BaseModel):
	city: str = Field(
		...,
		min_length=4,
		max_length=150,
		example = "Tigre"
		)
	state: str = Field(
		...,
		min_length=4,
		max_length=150,
		example="Buenos aires"
		)
	country: Optional[str] = Field(default=None, example = "Argentina")

Reto

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Medellin"
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Antioquia"
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="COL"
    )

Reto

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Bogota"
        )
    state: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Bogota.D.C"
        )
    country: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Colombia"
        )

Si los examples se ponen a nivel de campo puedes hacer con varios request body

Asi quedo el ejemplo

class Location(BaseModel):
    city: str = Field(
        title = "City of the person",
        description = "This field is important to get a good performance at the platform",
        example = "Puebla"
    )
    state: str = Field(
        title = "State of Person",
        description="It's important your state",
        example = "Puebla"
    )
    country: str = Field(
        title = "Country of person",
        description="It's important to know your location",
        example = "Mexico"
    )
Para hacerlo funcionar es importante quitar el "#" de la siguiente línea:
 Location: Location = Body(...)

Reto

Código


class Location(BaseModel):
    """Represents a location."""
    
    city: str
    state: str
    country: str

    class Config:
        schema_extra = {
            'example': {
                'city': 'New York',
                'state': 'NY',
                'country': 'USA'
            }
        }

Preview

Me agrada más indicar el ejemplo en el parámetro
Me queda la duda, cómo se podrian generar más casos con la clase config?
Tocará buscar en la doc

class Location(BaseModel):
    city: str = Field(
        ...,
        title='City location',
        description='City of the Person Location',
        example="Campeche",
        min_length = 2
        )
    state: str = Field(
        ...,
        title='State Location',
        description='State of the Person Location',
        example="Campeche",
        min_length = 2
        )
    country: str = Field(
        ...,
        title='Country Location',
        description='Country of the Person Location',
        example="México",
        min_length = 2
        )

No me funcionó usando la clase config, pero igual aquí va

class Location(BaseModel):
    city: str = Field(
        ...,
        title="city of the person",
        description="show the city of the person, between 3 and 150 characters",
        min_length=3,
        max_length=150,
        example="Asunción"

    )
    state:str = Field(
        ...,
        title="state of the person",
        description="show the state of the person, between 3 and 150 characters",
        min_length=3,
        max_length=150,
        example="Luque" 
    )
    country:str = Field(
        ...,
        title="country of the person",
        description="show the country of the person, between 3 and 150 characters",
        min_length=3,
        max_length=150,
        example="Paraguay"  
    )

Esta es otra forma incluyendo descripción y descomentado la linea de la parte final.

class Location(BaseModel):
    city: str = Field(
        ...,
        min_length=1,
        max_length=50,
        description="The city where the person lives",
        example="New York",
    )
    state: str = Field(
        ...,
        min_length=1,
        max_length=50,
        description="The state where the person lives",
        example="New York",
    )
    country: str = Field(
        ...,
        min_length=1,
        max_length=50,
        description="The country where the person lives",
        example="United States",
    )


	location: Location = Body(...)