DEV Community

abbazs
abbazs

Posted on

How to validate date using pydantic?

Consider you have a data model that has start date and end date, we need to validate the start date and the end date. Start date must be greater than 1-JAN-2020 and end date must be greater than start date.

How can we do that?

from datetime import date
from pydantic import BaseModel, field_validator

class DateModel(BaseModel):
    st_date: date
    nd_date: date

    # Field validator for st_date
    @field_validator('st_date')
    def validate_start_date(cls, value: date) -> date:
        # Check if the value is less than January 1, 2020
        if value < date(2020, 1, 1):
            # Raise a ValueError with the error message
            raise ValueError("Start date cannot be before January 1, 2020.")
        # Return the value if it passes validation
        return value

    # Field validator for nd_date
    @field_validator('nd_date')
    def validate_end_date(cls, value: date, values) -> date:
        # Retrieve the value of st_date field from the values dictionary
        start_date = values.get('st_date')
        # Check if nd_date is less than or equal to st_date
        if value <= start_date:
            # Raise a ValueError with the error message
            raise ValueError("End date must be greater than the start date.")
        # Return the value if it passes validation
        return value
Enter fullscreen mode Exit fullscreen mode

Is there a better way to do it?

Yes, following code reduces the need for start date validation by validator function. However, end date needs a validator function.

from datetime import date
from pydantic import BaseModel, Field, field_validator


class DateModel(BaseModel):
    # Define the st_date field with a validation rule using Field
    st_date: date = Field(..., gt=date(2020, 1, 1))

    # Define the nd_date field
    nd_date: date

    # Field validator for nd_date
    @field_validator("nd_date")
    def validate_end_date(cls, value: date, values, **kwargs) -> date:
        # Retrieve the value of nd_date field
        # Retrieve the value of st_date field from the values dictionary
        start_date = values.get("st_date")

        # Check if nd_date is less than or equal to st_date
        if value <= start_date:
            # Raise a ValueError with the error message
            raise ValueError("End date must be greater than the start date.")

        # Return the value if it passes validation
        return value
Enter fullscreen mode Exit fullscreen mode

This code is an improvement over the previous code in terms of readability and conciseness. It makes use of Pydantic's built-in validation features, specifically the Field class and the field_validator decorator. Here's an explanation of how this code is better:

  1. Simplified Field Validation: The code uses the Field class to define the st_date field with a validation rule. By specifying gt=date(2020, 1, 1), it ensures that the st_date field must be greater than January 1, 2020. This eliminates the need for a separate validation method.

  2. Improved Error Handling: In the previous code, the validation errors were raised as ValueError exceptions. In this code, the validation error is raised with the appropriate error message using the raise statement. This provides more meaningful error messages to the user.

What is not possible?

In Pydantic, you cannot reference other fields directly within the Field declaration.

The following code will not work!

from datetime import date
from pydantic import BaseModel, Field, field_validator


class DateModel(BaseModel):
    st_date: date = Field(..., gt=date(2020, 1, 1))
    nd_date: date = Field(..., gt=st_date)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)