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
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
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:
Simplified Field Validation: The code uses the
Field
class to define thest_date
field with a validation rule. By specifyinggt=date(2020, 1, 1)
, it ensures that thest_date
field must be greater than January 1, 2020. This eliminates the need for a separate validation method.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 theraise
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)
Top comments (0)