Using Pydantic with FastAPI for Data Validation
FastAPI is a modern Python framework that makes building APIs fast and easy. It integrates with Pydantic to provide automatic data validation and serialization. In this post, we'll explore how to use Pydantic models inside a FastAPI app.
1️⃣ Install FastAPI & Uvicorn
Before we start, install FastAPI and Uvicorn using pip:
pip install fastapi uvicorn pydantic
- FastAPI: The API framework.
- Uvicorn: ASGI server to run the FastAPI app.
2️⃣ Creating a Simple FastAPI App
Let's create a basic FastAPI app that accepts user data, validates it, and returns a response.
📌 Code: FastAPI with Pydantic
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
# Define a Pydantic model
class User(BaseModel):
id: int
name: str
age: int
email: EmailStr # Validates email format
# Endpoint to create a user
@app.post("/users/")
async def create_user(user: User):
return {"message": "User created successfully", "user": user}
# Run using: uvicorn filename:app --reload
3️⃣ Running the FastAPI App
Save the file as main.py and run:
uvicorn main:app --reload
Now, open your browser and visit:
- Swagger UI: 👉 http://127.0.0.1:8000/docs
- ReDoc UI: 👉 http://127.0.0.1:8000/redoc
4️⃣ Testing API with JSON Data
Use Swagger UI or Postman to send a POST request to /users/ with JSON:
{
"id": 1,
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}
✅ Success Response:
{
"message": "User created successfully",
"user": {
"id": 1,
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}
}
🚫 Validation Error (Invalid Email):
{
"detail": [
{
"loc": ["body", "email"],
"msg": "value is not a valid email address",
"type": "value_error.email"
}
]
}
5️⃣ Adding Custom Validation in Pydantic
We can enforce custom rules using @validator.
📌 Example: Restrict Age to 18+
from pydantic import validator
class User(BaseModel):
id: int
name: str
age: int
email: EmailStr
@validator("age")
def validate_age(cls, value):
if value < 18:
raise ValueError("Age must be 18 or older")
return value
Now, if a user under 18 tries to register, they’ll get a validation error.
6️⃣ Using Nested Pydantic Models
For complex objects, we can nest Pydantic models.
📌 Example: User with Address
from typing import List
class Address(BaseModel):
street: str
city: str
zip_code: str
class User(BaseModel):
id: int
name: str
age: int
email: EmailStr
address: Address # Nested Pydantic Model
@app.post("/users/")
async def create_user(user: User):
return {"message": "User created", "user": user}
Now, JSON requests must include an address:
{
"id": 2,
"name": "Bob",
"age": 30,
"email": "bob@example.com",
"address": {
"street": "456 Elm St",
"city": "Los Angeles",
"zip_code": "90001"
}
}
7️⃣ Returning Pydantic Models as API Responses
You can enforce structured responses with response_model.
📌 Example:
@app.post("/users/", response_model=User)
async def create_user(user: User):
return user
Now, FastAPI ensures that responses match the User model.
🎯 Conclusion
FastAPI + Pydantic provides:
✅ Automatic data validation
✅ Easy JSON serialization
✅ Swagger UI for testing
✅ Custom validators for business rules
Comments
Post a Comment