FastAPI: Modern Python APIs
Create high-performance APIs with FastAPI, automatic documentation, and type hints. Complete guide to building modern Python web APIs with FastAPI framework.
What You'll Master
FastAPI Fundamentals
Async programming, type hints, and automatic validation
Automatic Documentation
Interactive API docs with Swagger UI and ReDoc
Data Validation
Pydantic models for request/response validation
Authentication & Security
JWT, OAuth2, and dependency injection for security
Database Integration
SQLAlchemy, async database operations, and ORM
Testing & Deployment
Unit testing, async testing, and production deployment
Introduction to FastAPI
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints. It's designed to be easy to use and learn, fast to code, ready for production, and based on open standards.
Why Choose FastAPI?
FastAPI offers several advantages over traditional Python web frameworks:
- High Performance: One of the fastest Python frameworks available
- Automatic Documentation: Interactive API docs generated automatically
- Type Safety: Full support for Python type hints
- Easy to Use: Designed to be intuitive and easy to learn
- Standards Based: Built on OpenAPI, JSON Schema, and OAuth2
Getting Started with FastAPI
FastAPI is built on top of Starlette for the web parts and Pydantic for the data parts. It provides automatic request validation, serialization, and documentation generation.
Installation and Basic Setup
# Install FastAPI and Uvicorn
pip install fastapi uvicorn
# Create a simple API
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
# Run the server
# uvicorn main:app --reloadType Hints and Data Validation
FastAPI uses Python type hints to automatically validate request data and generate OpenAPI schemas. This provides excellent IDE support and runtime validation with minimal code.
Pydantic Models
from pydantic import BaseModel, EmailStr
from typing import Optional, List
from datetime import datetime
class UserBase(BaseModel):
email: EmailStr
full_name: str
is_active: bool = True
class UserCreate(UserBase):
password: str
class User(UserBase):
id: int
created_at: datetime
class Config:
orm_mode = True
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []API Endpoints and HTTP Methods
FastAPI makes it easy to create RESTful APIs with proper HTTP methods, status codes, and response models. You can define complex endpoints with path parameters, query parameters, and request bodies.
CRUD Operations
from fastapi import FastAPI, HTTPException, Depends
from typing import List
app = FastAPI()
# In-memory storage (use database in production)
items = []
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
items.append(item)
return item
@app.get("/items/", response_model=List[Item])
async def read_items(skip: int = 0, limit: int = 10):
return items[skip: skip + limit]
@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
if item_id >= len(items):
raise HTTPException(status_code=404, detail="Item not found")
return items[item_id]
@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, item: Item):
if item_id >= len(items):
raise HTTPException(status_code=404, detail="Item not found")
items[item_id] = item
return item
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
if item_id >= len(items):
raise HTTPException(status_code=404, detail="Item not found")
del items[item_id]
return {"message": "Item deleted"}Authentication and Security
FastAPI provides built-in support for various authentication methods including OAuth2, JWT tokens, and API keys. You can use dependency injection to handle authentication across your application.
JWT Authentication
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
return pwd_context.hash(password)
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
return usernameDatabase Integration
FastAPI works well with various databases through SQLAlchemy, databases, and other ORMs. You can use both synchronous and asynchronous database operations depending on your needs.
SQLAlchemy Integration
from sqlalchemy import Column, Integer, String, DateTime, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from fastapi import Depends
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
created_at = Column(DateTime)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/users/", response_model=User)
async def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = User(email=user.email, hashed_password=get_password_hash(user.password))
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_userTesting FastAPI Applications
FastAPI provides excellent testing support through the TestClient, which allows you to test your API endpoints without running a server. You can write comprehensive unit and integration tests.
Writing Tests
from fastapi.testclient import TestClient
import pytest
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello World"}
def test_create_item():
item_data = {
"name": "Test Item",
"description": "A test item",
"price": 9.99,
"tax": 1.0,
"tags": ["test", "example"]
}
response = client.post("/items/", json=item_data)
assert response.status_code == 200
data = response.json()
assert data["name"] == item_data["name"]
assert data["price"] == item_data["price"]
def test_read_item():
response = client.get("/items/0")
assert response.status_code == 200
data = response.json()
assert "name" in data
assert "price" in dataDeployment and Production
FastAPI applications can be deployed using various methods including Docker, cloud platforms, and traditional servers. Use ASGI servers like Uvicorn or Gunicorn for production deployment.
Docker Configuration
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# requirements.txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
pydantic==2.5.0
sqlalchemy==2.0.23Best Practices
- Type Hints: Use comprehensive type hints for better IDE support
- Error Handling: Implement proper exception handling and custom exceptions
- Documentation: Leverage automatic documentation generation
- Testing: Write comprehensive tests for all endpoints
- Security: Implement proper authentication and authorization
- Performance: Use async/await for I/O operations
Conclusion
FastAPI is an excellent choice for building modern Python APIs. Its combination of high performance, automatic documentation, type safety, and ease of use makes it ideal for both small projects and large-scale applications. With its growing ecosystem and community support, FastAPI is becoming the go-to framework for Python API development.