Muchas veces, encontramos que necesitamos pasar una larga lista de variables a una función, y especificar todo eso en la firma de la función de Python puede ser un poco complicado. Nuevamente, también surgen problemas cuando desea algún tipo de validación de las variables pasadas. Para una larga lista de variables, es realmente difícil seguir validando los datos dentro del cuerpo de la función principal, además, no es una buena práctica. En ese escenario, lo que desea hacer es separar y segregar sus variables en diferentes clases. Aquí, vamos a demostrar cómo puede usar pydantic para crear modelos junto con sus validaciones personalizadas. Primero, analicemos el caso de uso.
Considere, estamos recibiendo algunos datos de una llamada API, y necesitamos hacer algún tipo de análisis al respecto. Por lo general, una respuesta de API enviará la respuesta en forma de JSON, por lo que nos gustaría que nuestros modelos pudieran serializar y deserializar JSON (1) .
Además, asumiríamos tipos de ciertas variables. Por ejemplo, si estamos pasando una dirección, asumiríamos que el código PIN es un valor entero. Esta es la verificación de tipo (2) .
Para realizar el análisis, haría algunas suposiciones sobre los datos, como, por ejemplo, el código PIN debe coincidir con el nombre del distrito proporcionado. Esta es la validación (3) .
También podemos suponer que para ciertos campos como estados, debería estar dentro de una lista de estados, digamos en India, y no cualquier valor arbitrario aleatorio. Esto cae dentro de la limpieza (4) .
Entonces, con estos cuatro requisitos, comencemos a codificar el modo. Asumiría que tiene Python instalado en su sistema. Para instalar pydantic simplemente ejecute,
pip install pydantic
Con ese conjunto, cree un archivo llamado models.py y pegue el siguiente código en él. Hemos agregado comentarios detallados en línea en el propio código para que sea más fácil de entender directamente.
Python3
# import required modules from enum import Enum from typing import Optional from pydantic import BaseModel, PositiveInt, validator, root_validator, constr # custom class used as choices for state # pydantic choices using the built-in Enum of python # which reduces the need for additional packages class StateTypes(str, Enum): DELHI = "DLH" UTTAR_PRADESH = "UP" BENGALURU = "BLR" WEST_BENGAL = "WB" # class to get personal credentials class PersonalDetails(BaseModel): id: int # constr gives us the ability to specify # the min and max length name: constr(min_length=2, max_length=15 phone: PositiveInt # validation at field level @validator("phone") # get phone number def phone_length(cls, v): # phone number should typically be of length 10 if len(str(v)) != 10: raise ValueError("Phone number must be of ten digits") return v # class to get address class Address(BaseModel): id: int address_line_1: constr(max_length=50) # assigning some fields to be optional address_line_2: Optional[constr(max_length=50)] = None pincode: PositiveInt city: constr(max_length=30) # using choices in python is this simple. # Just create a class with Enums as choices # and the pass the class as type for the field state: StateTypes @validator("pincode") def pincode_length(cls, v): if len(str(v)) != 6: raise ValueError("Pincode must be of six digits") return v # using BaseModels as custom datatypes # in the User class class User(BaseModel): personal_details: PersonalDetails address: Address @root_validator(skip_on_failure=True) # skip_on_failure=True means it will skip the # validation for this class if it's custom # fields are not validated def check_id(cls, values): # custom validation ensuring personal_details.id is # same as address.id personal_details: PersonalDetails = values.get("personal_details") address: Address = values.get("address") if personal_details.id != address.id: raise ValueError( "ID field of both personal_details as well as address should match" ) return values # Driver Code if __name__ == "__main__": # testing models validated_data = { "personal_details": { "id": 1, "name": "GeeksforGeeks", "phone": 9999999999, }, "address": { "id": 1, "address_line_1": "Sector- 136", "pincode": 201305, "city": "Noida", "state": "UP", }, } # this would work without any error as # no validation will fail user = User(**validated_data) # would print the standard __str__ value for the model print(user) unvalidated_data = { "personal_details": { "id": 1, "name": "GeeksforGeeks", "phone": 9999999999, }, "address": { "id": 2, "address_line_1": "Sector- 136", "pincode": 201305, "city": "Noida", "state": "UP", }, } # this would raise a value error since the IDs # are different user = User(**unvalidated_data) print(user)
Producción:
Al ejecutar esto, la primera declaración de impresión se ejecutará con éxito, pero en la próxima inicialización del modelo de Usuario , arrojaría un Error de validación de tipo ValueError porque las ID de los detalles personales y la dirección no coinciden.
Publicación traducida automáticamente
Artículo escrito por debdutgoswami y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA