Pydantic Validators

7 min read Oct 08, 2024
Pydantic Validators

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.