FastAPI is a modern, high-performance Python web framework for building APIs. It offers automatic validation, documentation, and async support out of the box.
Getting Started
pip install fastapi uvicorn sqlalchemy pydantic
Basic API Structure
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
app = FastAPI(
title="My API",
description="A sample FastAPI application",
version="1.0.0"
)
# Pydantic models for validation
class ItemBase(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
description: Optional[str] = None
price: float = Field(..., gt=0)
class ItemCreate(ItemBase):
pass
class Item(ItemBase):
id: int
created_at: datetime
class Config:
from_attributes = True
# In-memory database
items_db = {}
item_counter = 0
@app.get("/")
async def root():
return {"message": "Welcome to the API"}
@app.get("/items", response_model=List[Item])
async def get_items():
return list(items_db.values())
@app.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail="Item not found")
return items_db[item_id]
@app.post("/items", response_model=Item, status_code=201)
async def create_item(item: ItemCreate):
global item_counter
item_counter += 1
new_item = Item(
id=item_counter,
created_at=datetime.now(),
**item.dict()
)
items_db[item_counter] = new_item
return new_item
@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, item: ItemCreate):
if item_id not in items_db:
raise HTTPException(status_code=404, detail="Item not found")
updated = Item(
id=item_id,
created_at=items_db[item_id].created_at,
**item.dict()
)
items_db[item_id] = updated
return updated
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail="Item not found")
del items_db[item_id]
return {"message": "Item deleted"}
Database Integration with SQLAlchemy
from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class ItemModel(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
description = Column(String(500))
price = Column(Float, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
# Dependency
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items/{item_id}")
async def get_item(item_id: int, db: Session = Depends(get_db)):
item = db.query(ItemModel).filter(ItemModel.id == item_id).first()
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
Authentication with JWT
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"])
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_token(data: dict):
return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
return None
async def get_current_user(token: str = Depends(oauth2_scheme)):
payload = verify_token(token)
if not payload:
raise HTTPException(status_code=401, detail="Invalid token")
return payload
@app.post("/token")
async def login(form: OAuth2PasswordRequestForm = Depends()):
# Validate user credentials
token = create_token({"sub": form.username})
return {"access_token": token, "token_type": "bearer"}
@app.get("/protected")
async def protected_route(user: dict = Depends(get_current_user)):
return {"message": f"Hello, {user['sub']}!"}
Run the Server
# Development
uvicorn main:app --reload
# Production
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
FastAPI auto-generates OpenAPI docs at /docs. It's production-ready out of the box!