Pydantic provides @validaor decorator to add custom validations to a model.
Let’s see it with an example.
class Employee(BaseModel):
id: int
name: str
age: int
@validator('name')
def nameValidator(cls, value):
if(len(value)< 5):
raise ValueError('name must contain atleast 5 characters')
return value
In the above example, I had written a validator for 'name' property, it throws value error when the name field contains less than 5 characters.
validator_demo_1.py
from pydantic import BaseModel, ValidationError, validator
from typing import Optional
class Employee(BaseModel):
id: int
name: str
age: int
@validator('name')
def nameValidator(cls, value):
if(len(value)< 5):
raise ValueError('name must contain atleast 5 characters')
return value
try:
emp1 = Employee(id = 1, age = 34, name='kri')
print(emp1)
except ValidationError as e:
print(e.json())
Output
[ { "loc": [ "name" ], "msg": "name must contain atleast 5 characters", "type": "value_error" }
Points to remember
a. Validators in Pydantic are modelled as class methods, so the first argument value they receive is the Employee class, not an instance of Employee.
b. Second argument is the actual field value to validate.
c. Validation is done in the order fields are defined.
Can I add multiple validators to a pydantic model?
Yes, you can.
validator_demo_2.py
from pydantic import BaseModel, ValidationError, validator
from typing import Optional
class Employee(BaseModel):
id: int
name: str
age: int
@validator('name')
def nameValidator(cls, value):
if(len(value)< 5):
raise ValueError('name must contain atleast 5 characters')
return value
@validator('age')
def ageValidator(cls, value):
if(value < 18):
raise ValueError('age should be >= 18')
return value
try:
emp1 = Employee(id = 1, age = 17, name='kri')
print(emp1)
except ValidationError as e:
print(e.json())
Output
[ { "loc": [ "name" ], "msg": "name must contain atleast 5 characters", "type": "value_error" }, { "loc": [ "age" ], "msg": "age should be >= 18", "type": "value_error" } ]
Can I apply a validator on multiple fields
Yes, you can.
validator_demo_3.py
from pydantic import BaseModel, ValidationError, validator
from typing import Optional
class Person(BaseModel):
id: int
name: str
age: int
@validator('age', 'id')
def ageAndIdValidator(cls, value):
if(value < 1):
raise ValueError('id and age must > 0')
return value
try:
p1 = Person(id = -1, age = -1, name='kri')
print(p1)
except ValidationError as e:
print(e.json())
Output
[ { "loc": [ "id" ], "msg": "id and age must > 0", "type": "value_error" }, { "loc": [ "age" ], "msg": "id and age must > 0", "type": "value_error" } ]
In the above example, I applied validator on both age and id.
Can I apply a validator on all the fields of a model?
Yes, by passing the special value '*', you can apply a validator on all the fields of a model.
validator_demo_4.py
from pydantic import BaseModel, ValidationError, validator
from typing import Optional
class Box(BaseModel):
id: int
weight: str
height: int
@validator('*')
def ageAndIdValidator(cls, value):
if(value < 1):
raise ValueError('id, weight and height must > 0')
return value
try:
b1 = Box(id = 1, weight = 0, height = 0)
print(b1)
except ValidationError as e:
print(e.json())
Output
[ { "loc": [ "weight" ], "msg": "'<' not supported between instances of 'str' and 'int'", "type": "type_error" }, { "loc": [ "height" ], "msg": "id, weight and height must > 0", "type": "value_error" } ]
No comments:
Post a Comment