Reusing Pydantic validators and serializers
Posted on 2025-04-21 in Trucs et astuces
I’ll give some tips to reuse field and model validators and serializers. All my examples will use validators, but it works exactly the same for serializers.
Field validators
Assign the validator to a variable like so:
def _is_above_ten(value: int): if value > 10: return value raise ValueError(f"{value} is not above 10") field_validator = AfterValidator(_is_above_ten) class MyModel(BaseModel): my_field: Annotated[int, field_validator]
Model validators
With inheritance
This is specially useful if all the models requiring the validator can inherit from the same base model.
class BaseModelWithValidators(BaseModel): my_field: int my_other_field: int @model_validator(mode="after") def my_validator(self) -> Self: if self.my_field > self.my_other_field: raise ValueError("my_field must be lower or equal to my_other_field") return self class MyChildModel(BaseModelWithValidators): third_field: int
With factories
You can achieve the same result with factories that will build the validator. It’s useful to avoid a type hierarchy since this gives you smaller pieces easier to combine. It also allows for the validator to have some configurations passed to it when the model is defined.
def validator_factory(min_value: int): @model_validator(mode="after") def my_validator(self) -> Self: if self.my_field > self.my_other_field: raise ValueError("my_field must be lower or equal to my_other_field") if self.my_field <= min_value: raise ValueError(f"my_field must be higher than {min_value}") return self return my_validator class ModelWithValidatorFactory(BaseModel): my_validator = validator_factory(80) my_field: int my_other_field: int