Create custom datatypes using Pydantic module in Python
Last Updated :
16 Aug, 2021
Many times, we find that we need to pass in a long list of variables to a function, and specifying all of that in the Python function signature can be a bit messy. Again, problems also arise when you want some kind of validation to variables passed. For a long list of variables, it is really difficult to keep validating the data inside the main function body, also it is not a good practice. In that scenario, what you want to do is separate and segregate your variables into different classes. Here, we are going to demonstrate how can use pydantic to create models along with your custom validations. First, let's discuss the use case.
Consider, we are receiving some data from an API call, and we need to do some kind of analysis on it. Typically, an API response will send the response in form of JSON, so we would want our models to be able to serialize and deserialize JSON (1).
Also, we would assume types of certain variables. For example, if we are passing an address, we would assume the pincode to be an Integer value. This is type checking (2).
To perform analysis, you would make some assumptions on the data, like say, pincode should match with the district name provided. This is validation (3).
We might also assume that for certain fields like states, it should be within a list of states say in India, and not any random arbitrary value. This falls under cleaning (4).
So, with these four requirements, let's start coding out mode. I would assume that you have python installed on your system. To, install pydantic simply run,
pip install pydantic
With that set, create a file called models.py and paste the below code in it. We have added detailed in-line comments in the code itself to make it easier to understand directly.
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)
Output:
Execution Screenshot
Upon running this, the first print statement will get executed successfully but in the next initialization of the User model, it would throw ValidationError of type ValueError because IDs of both personal details and address does not match.
Similar Reads
C Extension Module using Python
Writing a simple C extension module directly using Pythonâs extension API and no other tools. It is straightforward to make a handcrafted extension module for a simple C code. But first, we have to make sure that the C code has a proper header file. Code #1 : C #include <math.h> extern int gcd
4 min read
How to create a dataset using PyBrain?
In this article, we are going to see how to create a dataset using PyBrain. Dataset Datasets are the data that are specifically given to test, validate and train on networks. Instead of troubling with arrays, PyBrain provides us with a more flexible data structure using which handling data can be qu
3 min read
Convert Python String to Float datatype
Let us see how to convert a string object into a float object. We can do this by using these functions : float() decimal() Method 1: Using float() python3 # declaring a string str1 = "9.02" print("The initial string : " + str1) print(type(str1)) # converting into float str2 = flo
2 min read
How to create modules in Python 3 ?
Modules are simply python code having functions, classes, variables. Any python file with .py extension can be referenced as a module. Although there are some modules available through the python standard library which are installed through python installation, Other modules can be installed using t
4 min read
Convert JSON data Into a Custom Python Object
Let us see how to convert JSON data into a custom object in Python. Converting JSON data into a custom python object is also known as decoding or deserializing JSON data. To decode JSON data we can make use of the json.loads(), json.load() method and the object_hook parameter. The object_hook parame
2 min read
How to Create a Programming Language using Python?
In this article, we are going to learn how to create your own programming language using SLY(Sly Lex Yacc) and Python. Before we dig deeper into this topic, it is to be noted that this is not a beginner's tutorial and you need to have some knowledge of the prerequisites given below. PrerequisitesRou
7 min read
Using Pointers in Python using ctypes
In this article, we are going to learn about using pointers in Python using ctypes module. We will see how we can use Pointers in Python programming language using the ctypes module. Some basic operations like storing addresses, pointing to a different variable using pointers, etc. will be demonstra
10 min read
Create Plotly Express charts in less lines of code using Python and Datamallet
In this article, we will see how to create all possible Plotly express charts in very less lines of code using a new Python Module known as datamallet. Introduction to the datamallet Library According to the PyPi website datamallet library is made by Data Scientists to help fellow Data Scientists ea
5 min read
Make Every Field Optional With Pydantic in Python
We are given a task to make every field optional with Pydantic. In this article, we will see how to make every field as optional with Pydantic. Pydantic Models: Python classes are used to define Pydantic models. These models often include fields that are mandatory by default. However, you may use Py
2 min read
Introduction to Python Typing-Extensions Module
The typing-extensions module provides backports of the latest typing features to ensure that developers working with older versions of Python can still leverage these advanced tools. This module acts as a bridge between future releases of Python and existing codebases, enabling us to stay up to date
8 min read