Pydantic Validators: A Guide to Data Validation in Python
Pydantic is a Python library that defines data validation and parsing using type annotations. It provides a powerful way to ensure that your data conforms to a specific structure and that your applications are robust and reliable. One of the key features of Pydantic is its support for pydantic validators, which allow you to implement custom validation logic beyond the basic type checks.
Why Use Pydantic Validators?
Pydantic's built-in type annotations offer a basic level of validation, but they may not be sufficient for all scenarios. Pydantic validators give you the flexibility to perform more complex validation, such as:
- Custom checks: Validate data against specific business rules, such as ensuring a phone number is in a valid format or checking if a value is within a certain range.
- Conditional validation: Validate data based on the values of other fields within the model.
- Data transformations: Modify data before it is validated or stored.
How to Use Pydantic Validators
Pydantic validators are defined as functions decorated with @validator
. These functions receive the value being validated, the field name, and the Pydantic model as arguments.
Here's a basic example:
from pydantic import BaseModel, validator
class User(BaseModel):
username: str
email: str
age: int
@validator('age')
def age_must_be_positive(cls, value):
if value <= 0:
raise ValueError('Age must be positive')
return value
In this example, the age_must_be_positive
function is a validator for the age
field. It ensures that the age
value is greater than 0. If not, it raises a ValueError
.
Types of Validators:
- Field-level Validators: Applied to a specific field.
- Root Validators: Applied to the entire model.
- Pre and Post Validators: Applied before and after the default data validation.
Example: Conditional Validation
from pydantic import BaseModel, validator
class Order(BaseModel):
product_name: str
quantity: int
discount: float = 0
@validator('discount', always=True)
def discount_cannot_exceed_100(cls, value, values):
if values.get('quantity') > 10 and value > 0.5:
raise ValueError('Discount cannot exceed 50% for orders over 10 items')
return value
In this example, the discount_cannot_exceed_100
validator checks if the quantity
is greater than 10 and if the discount
exceeds 50%. This is a conditional validation, as the validation depends on the value of another field.
Example: Data Transformations
from pydantic import BaseModel, validator
class User(BaseModel):
first_name: str
last_name: str
full_name: str = None
@validator('full_name', pre=True, always=True)
def calculate_full_name(cls, value, values):
if value is None:
return f"{values['first_name']} {values['last_name']}"
return value
In this example, the calculate_full_name
validator is a pre validator, it transforms the full_name
field to create a full name from the first_name
and last_name
fields if not already provided.
Advanced Pydantic Validator Techniques
1. Using always
for Pre and Post Validators:
The always
argument ensures that the validator runs even if the field is missing or None. This is useful for pre-validation tasks like data transformations or for post-validation tasks like logging or data sanitization.
2. Accessing Other Fields with values
:
The values
argument in the validator function allows you to access the values of other fields within the model. This is useful for implementing conditional validations or for complex data transformations.
3. Using any
and each_item
for Lists and Dictionaries:
Pydantic provides the any
and each_item
keywords for validating individual elements within lists or dictionaries. This lets you apply validation to multiple values within a single field.
4. Custom Validator Errors:
You can customize the error messages raised by your validators by raising a ValueError
with a descriptive message.
5. Combining Pydantic Validators with Other Validation Libraries:
Pydantic validators can be used in conjunction with other validation libraries like schema
or marshmallow
for more comprehensive validation.
Conclusion
Pydantic validators are a powerful tool for building robust and reliable Python applications. They provide a flexible way to implement custom validation logic, handle conditional scenarios, and transform data as needed. By leveraging the features and techniques discussed in this article, you can ensure that your data meets your specific requirements and that your applications are free from unexpected errors.