In web development, data validation is a critical step to ensure the security and stable operation of applications. For example, during user registration, it is necessary to verify whether the username meets the rules, whether the age is a valid number, and whether the email format is correct. If the validation logic is improperly handled, it may result in error messages at best or even program crashes or security vulnerabilities at worst. As a high-performance Python web framework, FastAPI integrates the Pydantic library for data validation, making data validation simple and efficient.
I. What is Pydantic?¶
Pydantic is a Python library whose core functionality is data validation and settings management. It automatically checks whether input data conforms to model rules by defining data models (based on Python type hints) and provides clear error messages when data is invalid. FastAPI chose Pydantic as its data validation tool because it:
- Is compatible with Python native type hints, requiring no additional learning of complex syntax;
- Automatically handles type conversion (e.g., string to integer);
- Includes built-in common validation logic (required fields, default values, format validation, etc.);
- Provides user-friendly error messages for easier front-end debugging.
II. Quick Start: Define Your First Pydantic Model¶
Pydantic models are defined by inheriting from BaseModel, with field types specified by Python type hints. Here is a simple example of a user information model:
from pydantic import BaseModel
class User(BaseModel):
name: str # String type, required (no default value)
age: int = 18 # Integer type, optional (default value 18)
email: str | None = None # String or None, optional (default None)
Key Points:
- Required Fields: If a field has no default value (e.g., name), it must be provided by the user; otherwise, FastAPI will return a “field required” error.
- Optional Fields: If a field has a default value (e.g., age and email), users can omit it and use the default value.
- Type Hints: Supports basic types like int, str, bool, and complex types like list and dict (e.g., hobbies: list[str]).
III. Using Pydantic to Handle Request Data in FastAPI¶
In FastAPI, Pydantic models are most commonly used to process request data (e.g., the request body in a POST request). FastAPI automatically parses the request body data into a Pydantic model and validates its legality. If validation fails, FastAPI returns a 422 error with detailed error messages.
Step 1: Define the Pydantic Model¶
from pydantic import BaseModel
from fastapi import FastAPI
# Define user registration request model
class UserCreate(BaseModel):
name: str # Required, string
age: int # Required, integer (no default value)
email: str # Required, string (custom validation to be added later)
Step 2: Use the Model in a Route Function¶
FastAPI route functions can directly specify parameters of Pydantic model types, and FastAPI will automatically parse the request body and validate the data:
app = FastAPI()
@app.post("/users/register")
def register_user(user: UserCreate):
# After successful validation, 'user' is an instance of UserCreate and can be used directly
return {
"message": f"User registration successful! Welcome, {user.name} ({user.age} years old)",
"email": user.email
}
Test the Validation Effect¶
After starting the FastAPI service, you can test the validation with a POST request:
- Normal Request: {"name": "小明", "age": 20, "email": "xiaoming@example.com"} → Returns a success message;
- Error Request: {"name": "小红", "age": "abc"} (invalid age type) → FastAPI automatically returns a 422 error with the following content:
{
"detail": [
{
"loc": ["body", "age"],
"msg": "Input should be a valid integer",
"type": "type_error.integer"
}
]
}
IV. Response Data Validation: Ensure Correct Return Format¶
Pydantic can also be used to validate response data (e.g., JSON returned to the front-end) to ensure the returned format meets expectations. For example, define a model to return user information:
class UserResponse(BaseModel):
id: int # User ID (assumed generated by the database)
name: str
age: int
email: str | None = None # Optional field
@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
# Simulate fetching user data from the database
user_data = {
"id": user_id,
"name": "Test User",
"age": 25,
"email": "test@example.com"
}
return user_data # FastAPI automatically validates if the return data conforms to the UserResponse model
Key Points:
- Use the response_model=UserResponse parameter, and FastAPI will automatically serialize the returned data into the format defined by UserResponse.
- If the returned data contains fields outside the model (e.g., an extra token), FastAPI will automatically filter them to ensure only the fields defined in the model are returned.
V. Advanced: Custom Validation Rules¶
Pydantic supports more complex validation requirements, such as limiting numerical ranges and custom formats (e.g., email). This can be achieved through the following methods:
1. Use Field to Set Field Constraints¶
The Field function can specify additional rules for fields (e.g., minimum/maximum length, regular expressions):
from pydantic import BaseModel, Field, EmailStr
class UserCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=20) # Name length 2-20
age: int = Field(gt=0, lt=150) # Age: 0 < age < 150
email: EmailStr = Field(...) # Automatically validates email format (requires 'pydantic[email]' installation)
2. Custom Validation Functions¶
Use the @field_validator decorator to define custom validation logic (e.g., email format):
from pydantic import BaseModel, field_validator
import re
class UserCreate(BaseModel):
name: str
age: int
email: str
@field_validator('email') # Validate the 'email' field
def email_format(cls, v):
if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', v):
raise ValueError('Invalid email format')
return v # Return the original value if validation passes
VI. Summary¶
Pydantic acts as a “data validation butler” in FastAPI, simplifying API development with the following advantages:
- Automatic Validation: FastAPI + Pydantic automatically intercepts invalid data without manual if-else checks;
- Error Messages: Clear error messages help front-end developers quickly identify issues;
- Type Safety: Avoid program crashes caused by data type errors;
- Flexible Extension: Supports basic types, complex structures, custom rules, etc., meeting various validation needs.
For FastAPI beginners, mastering basic Pydantic usage (defining models, route parameters, error handling) is essential for developing secure and robust APIs.
Tip: For further learning, refer to the official Pydantic documentation (https://docs.pydantic.dev/latest/) to explore advanced features like nested models, list nesting, and ORM integration (orm_mode=True).