FastAPI Pydantic Model
Pydantic is a core dependency of FastAPI, used for data validation and serialization. It lets you define data models using standard Python type annotations, automatically handling data validation, type conversion, and documentation generation.
What is Pydantic
Pydantic is a Python data validation library. Its core philosophy is:Define data structures with Python type annotations, and Pydantic automatically handles validation and conversionIn FastAPI, Pydantic is mainly used for:
| Purpose | Description |
|---|---|
| Request body validation | Automatically validate whether JSON data sent by clients conforms to the model definition |
| Response body serialization | Automatically convert model data into JSON responses |
| Automatic documentation | Model fields, types, and validation rules automatically appear in the API documentation |
| Editor support | Model attributes get full autocompletion in the editor |
Define Pydantic models
Create an inheritanceBaseModelclasses that declare fields using standard Python types:
Example
class Item(BaseModel):
name: str # Required: Product name
description: str | None = None # Optional: Product description
price: float # Required: Product price
tax: float | None = None # Optional: tax
Whether a field is required depends on whether it has a default value:
| Fields | Declaration method | Required? |
|---|---|---|
name | name: str | Required |
description | description: str | None = None | Optional |
price | price: float | Required |
tax | tax: float | None = None | Optional |
Use Pydantic models
As request body
The most common usage is declaring a model as a parameter of a path operation function:
Example
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.post("/items/")
async def create_item(item: Item):
# FastAPI automatically validates the request body and, after validation passes, assigns it to the item parameter
return item
Access and manipulate model data
Example
async def create_item(item: Item):
# Access model attributes
print(item.name) # Directly access attributes
print(item.price) # Editor provides auto-completion
# Serialize to dictionary
item_dict = item.model_dump()
print(item_dict) # {"name": "Foo", "description": None, "price": 45.2, "tax": None}
# Serialize to JSON string
item_json = item.model_dump_json()
print(item_json) # '{"name":"Foo","description":null,"price":45.2,"tax":null}'
return item_dict
Pydantic v2 Usage
model_dump()andmodel_dump_json()Replaces v1'sdict()andjson()method. The new method has better performance (implemented in Rust under the hood).
Model validation example
When data sent by a client does not conform to the model definition, FastAPI returns detailed validation errors:
Example
POST /items/
{
"description": "missing name and price"
}
# FastAPI Response Validation Error
{
"detail": [
{
"type": "missing",
"loc": ["body", "name"],
"msg": "Field required",
"input": {"description": "missing name and price"}
},
{
"type": "missing",
"loc": ["body", "price"],
"msg": "Field required",
"input": {"description": "missing name and price"}
}
]
}
If incorrectly typed data is sent:
// price 应该是数字,但传了字符串
{
"name": "Foo",
"price": "not a number"
}
// FastAPI 返回的错误
{
"detail": [
{
"type": "float_parsing",
"loc": ["body", "price"],
"msg": "Input should be a valid number, unable to parse string as a number",
"input": "not a number"
}
]
}
Common Pydantic v2 methods
| Methods | v2 (Recommended) | v1 (deprecated) | Description |
|---|---|---|---|
| Serialize to dictionary | item.model_dump() | item.dict() | Convert a model into a Python dictionary |
| Serialize to JSON | item.model_dump_json() | item.json() | Convert model to JSON string |
| Create from dictionary | Item.model_validate(data) | Item.parse_obj(data) | Create and validate a model from a dictionary |
| Create from JSON | Item.model_validate_json(json_str) | Item.parse_raw(json_str) | Create a model from a JSON string |
| Get JSON Schema | Item.model_json_schema() | Item.schema() | Obtaining the model's JSON Schema |
Model configuration (model_config)
Pydantic v2 Usagemodel_configReplaces v1'sConfigInner class:
Example
class Item(BaseModel):
name: str
price: float
# Pydantic v2 configuration method
model_config = ConfigDict(
json_schema_extra={ # Display examples in the API documentation
"examples": [
{
"name": "Foo",
"price": 35.4
}
]
}
)
In Pydantic v2,
orm_mode = Truechanged tofrom_attributes = True,schema_extrachanged tojson_schema_extra,allow_population_by_field_namechanged topopulate_by_name。
Model inheritance
Pydantic models support inheritance, making it easy to create input models and output models:
Example
# Base Model
class UserBase(BaseModel):
username: str # Required
email: EmailStr # Required, automatically validates email format
full_name: str | None = None # Optional
# Input model for creating a user (including password)
class UserCreate(UserBase):
password: str # Required
# Output model for returning user information (does not include password)
class UserOut(UserBase):
id: int # Generated by the server
# Usage example
@app.post("/users/", response_model=UserOut)
async def create_user(user: UserCreate):
# Function receives UserCreate (with password), but response uses UserOut (without password)
# This way the password will not appear in the API response.
return {"id": 1, **user.model_dump(exclude={"password"})}
Using different input and output models is an important means of protecting sensitive data. Never return sensitive fields such as passwords in API responses.
Summary
Key points of Pydantic models:
- Usage
BaseModelDefine data models with standard Python types declaring fields - Fields with default values are optional, fields without default values are required
- v2 usage
model_dump()、model_validate()and other new methods - Create different input/output models through model inheritance to protect sensitive data
- All validation and documentation are automatic—just declare types once