How to Use model_validator in Pydantic with FastAPI
Use
@model_validator decorator inside a Pydantic model to add custom validation logic that runs on the whole model. In FastAPI, define this inside your request or response model to validate or transform data after standard field validation.Syntax
The @model_validator decorator is applied to a class method inside a Pydantic model. This method receives the entire model data as input and returns the validated or modified data.
Use mode='before' to validate before field parsing, or mode='after' to validate after fields are parsed.
python
from pydantic import BaseModel, model_validator class MyModel(BaseModel): name: str age: int @model_validator(mode='after') def check_age(cls, values): if values.age < 18: raise ValueError('Age must be at least 18') return values
Example
This example shows a FastAPI app using a Pydantic model with @model_validator to ensure the age is at least 18. If validation fails, FastAPI returns a 422 error.
python
from fastapi import FastAPI from pydantic import BaseModel, model_validator app = FastAPI() class User(BaseModel): name: str age: int @model_validator(mode='after') def validate_age(cls, values): if values.age < 18: raise ValueError('User must be at least 18 years old') return values @app.post('/users/') async def create_user(user: User): return {'message': f'User {user.name} is valid and created.'}
Output
POST /users/ with {"name": "Alice", "age": 20} returns {"message": "User Alice is valid and created."}
POST /users/ with {"name": "Bob", "age": 16} returns 422 Unprocessable Entity with validation error "User must be at least 18 years old"
Common Pitfalls
- Using
@model_validatorwithout specifyingmodedefaults toafter, which runs after field parsing. - Raising generic exceptions instead of
ValueErrororTypeErrormay not produce clear validation errors. - Not returning the modified or original values from the validator method will cause errors.
- Trying to mutate the model instance directly instead of returning new values causes unexpected behavior.
python
from pydantic import BaseModel, model_validator class WrongModel(BaseModel): age: int @model_validator() def bad_validator(cls, values): if values.age < 0: # Wrong: raising generic Exception raise Exception('Age cannot be negative') # Wrong: not returning values class CorrectModel(BaseModel): age: int @model_validator(mode='after') def good_validator(cls, values): if values.age < 0: raise ValueError('Age cannot be negative') return values
Quick Reference
model_validator decorator usage:
@model_validator(mode='before'): Validate raw input data before field parsing.@model_validator(mode='after'): Validate parsed model data after field parsing.- Validator method must be a
classmethodreceivingclsandvalues. - Always return the validated or modified
values. - Raise
ValueErrororTypeErrorfor validation errors.
Key Takeaways
Use @model_validator inside Pydantic models to add custom validation logic for the whole model.
Specify mode='before' or mode='after' to control when validation runs relative to field parsing.
Always return the validated data from the validator method to avoid errors.
Raise ValueError or TypeError for clear validation error messages in FastAPI.
In FastAPI, model_validator helps enforce complex rules beyond simple field types.