No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Validaciones: Models

16/20
Recursos

Aportes 9

Preguntas 7

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Todos mis apuntes en https://rain-scabiosa-74f.notion.site/Curso-de-FastAPI-c414d59370504c448505a80b69f93b12

Diferencia Path, Query Parameters and Request Body

usamos Path Parameters cuando por ejemplo se trata de un id y esas cosas, como una variable etc, usamos los Requests Body para enviar información que tiene formato de un modelo y usamos los Query Parameters para solicitar infomación opcional del servidor.

Validaciones Models

Para validar modelos tomamos uso de la clase de Pydantic Field, que funciona igual a las validaciones que ya hemos hecho con Path, Query y Body

from pydantic import BaseModel, Field

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=110
    )
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)

Puedes ver que en hair_color ya tenemos un tipo distinto a String esto lo hacemos para validar que tenga un campo permitido, haciendo otra clase usando Enum

from enum import Enum

class HairColor(Enum):
    white: str = 'white'
    black: str = 'black'
    brown: str = 'brown'
    red: str = 'red'
    blonde: str = 'blonde'
    tinted: str = 'tinted'

Aquí tenemos enumerados algunos colores de pelo y ahora cada vez que alguien trate de ingresar un valor que no se encuentra en nuestra clase que hereda de Enum, le arrojará un error 422 Unprocessable Entity con el siguiente mensaje

{
  "detail": [
    {
      "loc": [
        "body",
        "person",
        "hair_color"
      ],
      "msg": "value is not a valid enumeration member; permitted: 'white', 'black', 'brown', 'red', 'blonde', 'tinted'",
      "type": "type_error.enum",
      "ctx": {
        "enum_values": [
          "white",
          "black",
          "brown",
          "red",
          "blonde",
          "tinted"
        ]
      }
    }
  ]
}

Codigo realizado hasta el momento

# Comando para inicializar la api  uvicorn main:app --reload
# --reload es un comando que nos permite visualizar los cambios en la api de forma automatica, sin la necesidad de recargar
# Python
from typing import Optional
from enum import Enum

# Pydantic
from pydantic import BaseModel, Field

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

app = FastAPI() # Almacenamos nuestro aplicativo en esta variable instanciando FastAPI

# Models
# Modelo de especificación de colores de cabello
class HairColor(Enum):
    white = 'white'
    black = 'black'
    brown = 'brown'
    blonde = 'blonde'


class Location(BaseModel):
    city: str
    state: str
    contry: str


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=8,
        le=110
    )
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)


@app.get('/')
def home():
    return {'Hello':'World'} # Retornamos un valor JSON


# 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(
    # Especificamos un limite de longitud para el ingreso de parametros
    name: Optional[str] = Query(
        None,
        min_length = 1,
        max_length = 40,
        title = 'Person Name',
        description = 'This is the person name. It\'s between 1 and 50 characters'
    ), 
    # No es recomendable, Los query parameteres deberian ser opcionales, pero en algun caso de la siguiente manera se puede hacer obligatorio
    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 = 'This is the person Id, It\'s required'
    )
):
    return {person_id: 'It exists!'}


# 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 ID'
    ),
    # Combinacion de dos request body
    person: Person = Body(...),
    location: Location = Body(...)
):
    # Para retornar el valor de dos request body necesitamos convertir de formato json a diccionario e imprimirlos ahora si
    results = person.dict()
    results.update(location.dict())
    return results

Buenas, dejo mi código, vuelvo a poner una regex para el nombre y apellido para que solo permita carácteres alfabéticos, sin “ñ”, “tildes” y sin espacios (esto ha sido por practicar, luego dejaré “ñ”, tildes, guión medio por apellido compuesto y un espacio para nombres compuestos y derivados.

# Python
from typing import Optional
from enum import Enum

# Pydantic
from pydantic import BaseModel, Field

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

app: FastAPI = FastAPI()


# Models

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


class Location(BaseModel):
    city: str
    state: str
    country: str


class Person(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=30,
        regex='^[A-Za-z]*$',
    )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=30,
        regex='^[A-Za-z]*$',
    )
    age: int = Field(
        ...,
        gt=0,
        le=115
    )
    hair_color: Optional[HairColor] = Field(default=None)
    is_married: Optional[bool] = Field(default=None)


@app.get('/')
def home():
    # def home() -> Dict:
    # def home() -> Dict[str, str]:
    return {"Hi": "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=30,
        regex='^[A-Za-z]*$',
        title="Person Name",
        description="This is the person name. It's between 1 and 30 characters"
    ),
    age: int = 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(
        ...,
        title="Person ID",
        description="This is the person ID. It's required",
        gt=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 person ID to update. It's required",
        gt=0
    ),
    person: Person = Body(...),
    location: Location = Body(...)

):
    return person.dict() | location.dict()

Un saludo.

La clase estuvo genial pero la que viene lo es TODO:

#Python
from typing import Optional
from fastapi.params import Path
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'
    black = 'black'
    blonde = 'blonde'
    brown = 'brown'
    red = 'red'

class Location(BaseModel):
    city: str
    state: str
    country: str
    latam: bool

class Person(BaseModel): # Person parameters
    first_name: str = Field(
        ...,
        min_length=3,
        max_length=35
        )
    last_name: str = Field(
        ...,
        min_length=3,
        max_length=35
        )
    age_person: int = Field(
        ...,
        gt=18,
        le=115
        )
    color_hair: Optional[HairColor] = Field(default=None)
    married: Optional[bool] = Field(default=None)

@app.get("/") #Path operation decorator
def home(): #Path operation function
    return {"First API": "Congratulation"} #JSON

# Request and Response Bondy

@app.post("/person/new") # Acces a new person
def create_person(person: Person = Body(...)): # acces to the parameters of person
    return person

# Validations: Query Parameters

@app.get("/person/detail")
def show_person(
    name: Optional[str] = Query(
        None, 
        min_length=3, 
        max_length=35,
        title="Person Name",
        description="This is the person name. It's between 3 and 35 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 reqiuired and it's more than 0."
        )
):
    return {person_id: "it_exist!"}

# 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(...)
):
    results = person.dict()
    results.update(location.dict())
    return results 

Si quieren que el programa sea muy óptimo, y no tener que actualizar la fecha, pueden usar el dato Birthday, de está manera.

# Importando date de datetime
from datetime import data as data_type

    birthday: date_type = Field(
        ...,
        alias='date'
        )

Mi Código hasta esta clase

# Python
from typing import 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
from pydantic import BaseModel, Field # Sirve para definir los modelos de datos que se usaran en la aplicacion

# 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
    country: str
    state: str
    lat: float
    lon: float

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 )
    hair_color: Optional[HairColor] = Field(default = None)
    is_married: Optional[bool] = Field(default = None)
    

@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
  

PUT

<code> 
from typing import Optional
from enum import Enum
from pydantic import BaseModel
from pydantic import Field
from fastapi import FastAPI
from fastapi import Body, Query

app = FastAPI()

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

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)
	is_maried: Optional[booL] = Field(default=None)


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

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

@app.get("/person/detail")
def show_person(
	name: Optional[str] = Query(None, min_Length=1, max_Length=50)
	age: str = Query(...)
):
	return{name: age}
class Location(BaseModeL):
	city: str
	state: str
	country: str


@app.put("/person/{person_id}")
def update_person(
	person_id: = 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 person

Validations: Model (Relacionado con request body)
from pydantic import field
from enum import enum (Nos permite enumerar caracteres
Para Enum se crea un modelo y se hereda en el tipo del atributo que se requiere)

validar los distintos tipos de datos