YouTip LogoYouTip

Fastapi Pydantic

Pydantic is a core dependency of FastAPI, used for data validation and serialization. It allows you to define data models using standard Python type annotations, automatically performing data validation, type conversion, and documentation generation. * * * ## What is Pydantic Pydantic is a Python data validation library, and its core idea is: **Define data structures using Python type annotations, and Pydantic automatically handles validation and conversion**. In FastAPI, Pydantic is mainly used for: | Usage | Description | | --- | --- | | Request Body Validation | Automatically validates whether client-sent JSON data matches the model definition | | Response Body Serialization | Automatically converts model data to JSON responses | | Auto Documentation | Model fields, types, and validation rules automatically appear in API documentation | | Editor Support | Model properties get full auto-completion in the editor | * * * ## Define Pydantic Models Create a class that inherits from `BaseModel`, using standard Python type declarations for fields: ## Example from pydantic import BaseModel class Item(BaseModel): name: str# Required: item name description: str | None=None# Optional: item description price: float# Required: item price tax: float | None=None# Optional: tax Whether a field is required depends on whether it has a default value: | Field | Declaration | 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 to declare the model as a parameter for the path operation function: ## Example from fastapi import FastAPI 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; after validation passes, it assigns to the item parameter return item ### Access and Manipulate Model Data ## Example @app.post("/items/") async def create_item(item: Item): # Access model properties print(item.name)# Access property directly 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 uses `model_dump()` and `model_dump_json()` to replace v1's `dict()` and `json()` methods. The new methods have better performance (implemented in Rust under the hood). * * * ## Model Validation Example When the client sends data that doesn't match the model definition, FastAPI returns detailed validation errors: ## Example # Client sends data with missing required fields POST /items/ { "description": "Missing name and price" } # FastAPI returns validation errors { "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 data with type errors is sent: // price should be a number, but a string was passed{ "name": "Foo", "price": "not a number"}// FastAPI returns the error{ "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 | Method | v2 (Recommended) | v1 (Deprecated) | Description | | --- | --- | --- | --- | | Serialize to dict | `item.model_dump()` | `item.dict()` | Convert model to Python dictionary | | Serialize to JSON | `item.model_dump_json()` | `item.json()` | Convert model to JSON string | | Create from dict | `Item.model_validate(data)` | `Item.parse_obj(data)` | Create and validate model from dictionary | | Create from JSON | `Item.model_validate_json(json_str)` | `Item.parse_raw(json_str)` | Create model from JSON string | | Get JSON Schema | `Item.model_json_schema()` | `Item.schema()` | Get model's JSON Schema | * * * ## Model Configuration (model_config) Pydantic v2 uses `model_config` to replace v1's internal `Config` class: ## Example from pydantic import BaseModel, ConfigDict class Item(BaseModel): name: str price: float # Pydantic v2 configuration method model_config = ConfigDict( json_schema_extra={# Show examples in API documentation "examples": [ { "name": "Foo", "price": 35.4 } ] } ) > In Pydantic v2, `orm_mode = True` has been changed to `from_attributes = True`, `schema_extra` has been changed to `json_schema_extra`, and `allow_population_by_field_name` has been changed to `populate_by_name`. * * * ## Model Inheritance Pydantic models support inheritance, making it easy to create input models and output models: ## Example from pydantic import BaseModel, EmailStr # Base model class UserBase(BaseModel): username: str# Required email: EmailStr # Required, automatically validates email format full_name: str | None=None# Optional # Input model when creating a user (includes password) class UserCreate(UserBase): password: str# Required # Output model when returning user info (excludes password) class UserOut(UserBase): id: int# Generated by server # Usage example @app.post("/users/", response_model=UserOut) async def create_user(user: UserCreate): # Function receives UserCreate (includes password), but response uses UserOut (excludes password) # This way the password won't appear in the API response return{"id": 1, **user.model_dump(exclude={"password"})} > Using different input and output models is an important way to protect sensitive data. Never return sensitive fields like passwords in API responses. * * * ## Summary Key points of Pydantic models: * Use `BaseModel` to define data models, with standard Python type declarations for fields * Fields with default values are optional, fields without default values are required * v2 uses new methods like `model_dump()` and `model_validate()` * Use model inheritance to create different input/output models to protect sensitive data * All validation and documentation is automatic - just declare types once
← Fastapi FormFastapi Route β†’