Pydantic support was added in version 3.0.0 through the new schema adapter system.
Pydantic 2.x
This documentation uses Pydantic 2.x (2.0+). If you're using Pydantic 1.x, please refer to the Pydantic V2 migration guide.
APIFlask supports Pydantic models alongside marshmallow schemas. You can use Pydantic's type-hint based approach for defining data models and validation.
Here's how to define and use Pydantic models with APIFlask:
fromenumimportEnumfromtypingimportOptionalfrompydanticimportBaseModel,FieldfromapiflaskimportAPIFlaskapp=APIFlask(__name__)classPetCategory(str,Enum):dog='dog'cat='cat'bird='bird'fish='fish'classPetIn(BaseModel):name:str=Field(min_length=1,max_length=50,description='Pet name')category:PetCategory=Field(description='Pet category')age:Optional[int]=Field(default=None,ge=0,le=30,description='Pet age')classPetOut(BaseModel):id:int=Field(description='Pet ID')name:str=Field(description='Pet name')category:PetCategory=Field(description='Pet category')age:Optional[int]=Field(default=None,description='Pet age')@app.post('/pets')@app.input(PetIn)@app.output(PetOut,status_code=201)defcreate_pet(json_data:PetIn):# json_data is automatically validated and deserialized into a PetIn instancenew_pet=PetOut(id=1,name=json_data.name,category=json_data.category,age=json_data.age)returnnew_pet
Pydantic 2.x provides @field_validator for field-level validation:
frompydanticimportBaseModel,field_validator,Field,ValidationErrorclassProductIn(BaseModel):name:str=Field(min_length=1)price:float=Field(gt=0)category:str@field_validator('name')@classmethoddefname_must_be_alphanumeric(cls,v:str)->str:ifnotv.replace(' ','').isalnum():raiseValueError('Name must be alphanumeric')returnv.title()@field_validator('category')@classmethoddefvalidate_category(cls,v:str)->str:categories=['electronics','clothing','books','home']ifv.lower()notincategories:raiseValueError(f'Category must be one of {categories}')returnv.lower()
For more complex validation across multiple fields, use @model_validator:
fromdatetimeimportdatetimefrompydanticimportBaseModel,model_validator,FieldclassDateRange(BaseModel):start_date:datetimeend_date:datetimemin_duration_days:int=Field(default=1,ge=1)@model_validator(mode='after')defcheck_dates(self)->'DateRange':ifself.end_date<=self.start_date:raiseValueError('end_date must be after start_date')duration=(self.end_date-self.start_date).daysifduration<self.min_duration_days:raiseValueError(f'Duration must be at least {self.min_duration_days} days')returnself
Pydantic validation errors are automatically converted to APIFlask's standard error format:
# When validation fails, you'll get structured error responses like:{'message':'Validation error','detail':{'json':{'age':['ensure this value is greater than or equal to 0'],'category':['Category must be one of [\'dog\', \'cat\', \'bird\', \'fish\']']}}}