DEV Community

abbazs
abbazs

Posted on

3

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

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay