Table of Contents
- Introduction to FastAPI
- Project Setup
- Folder Structure (Production Grade)
- Basic FastAPI Application
- Path Parameters, Query Parameters, and Request Bodies
- Pydantic Models for Data Validation
- CRUD with SQL Databases (MySQL/MariaDB)
- Dependency Injection
- Exception Handling
- Standardized Response Structure
- Authentication & Authorization
- Testing FastAPI Applications
- Running in Production
- Documentation & OpenAPI
- Conclusion
1. π Introduction to FastAPI
FastAPI is a modern, high-performance, Python web framework for building APIs with:
- Type hints
- Automatic validation
- Auto-generated Swagger UI
- ASGI (async support)
2. βοΈ Project Setup
π¦ Install FastAPI and Uvicorn
pip install fastapi uvicorn
For MySQL support:
pip install sqlalchemy pymysql alembic
3. π Folder Structure (Production Grade)
app/
βββ api/
β βββ routes/
β β βββ user.py
β βββ dependencies.py
βββ core/
β βββ config.py
β βββ security.py
βββ db/
β βββ base.py
β βββ session.py
β βββ models/
β βββ user.py
β βββ crud/
β βββ user.py
βββ schemas/
β βββ user.py
βββ services/
β βββ user_service.py
βββ main.py
βββ exceptions/
βββ handlers.py
4. π§± Basic FastAPI Application
main.py
:
from fastapi import FastAPI
from app.api.routes import user
from app.exceptions.handlers import add_exception_handlers
app = FastAPI(title="FastAPI CRUD App")
app.include_router(user.router, prefix="/api/v1/users")
add_exception_handlers(app)
5. π₯ Handling Parameters
from fastapi import FastAPI, Query, Path
@app.get("/items/{item_id}")
def read_item(item_id: int = Path(...), q: str = Query(None)):
return {"item_id": item_id, "q": q}
6. π Pydantic Models
schemas/user.py
from pydantic import BaseModel, EmailStr
class UserCreate(BaseModel):
name: str
email: EmailStr
password: str
class UserRead(BaseModel):
id: int
name: str
email: EmailStr
class Config:
orm_mode = True
7. ποΈ CRUD with SQLAlchemy
db/session.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "mysql+pymysql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db/models/user.py
from sqlalchemy import Column, Integer, String
from app.db.base import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50))
email = Column(String(100), unique=True, index=True)
password = Column(String(100))
db/base.py
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
db/crud/user.py
from sqlalchemy.orm import Session
from app.db.models.user import User
from app.schemas.user import UserCreate
def create_user(db: Session, user: UserCreate):
db_user = User(**user.dict())
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
def get_users(db: Session, skip: int = 0, limit: int = 10):
return db.query(User).offset(skip).limit(limit).all()
8. π§© Dependency Injection
api/dependencies.py
from app.db.session import SessionLocal
from fastapi import Depends
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
9. β Exception Handling
exceptions/handlers.py
from fastapi import Request, FastAPI
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
def add_exception_handlers(app: FastAPI):
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={"detail": exc.errors(), "body": exc.body},
)
@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"message": "Internal server error"},
)
10. π¦ Standardized Response Structure
Use a common response model:
from pydantic import BaseModel
from typing import Generic, TypeVar, Optional
T = TypeVar("T")
class ResponseModel(BaseModel, Generic[T]):
success: bool
message: str
data: Optional[T] = None
Use it in endpoints:
@app.post("/", response_model=ResponseModel[UserRead])
def create(user: UserCreate, db: Session = Depends(get_db)):
new_user = crud.create_user(db, user)
return ResponseModel(success=True, message="User created", data=new_user)
11. π Authentication & Authorization
core/security.py
:
from passlib.context import CryptContext
from jose import jwt
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
def hash_password(password: str):
return pwd_context.hash(password)
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def create_access_token(data: dict):
return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
Use OAuth2PasswordBearer from fastapi.security
.
12. π§ͺ Testing FastAPI Applications
test_main.py
:
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_create_user():
response = client.post("/api/v1/users", json={"name": "Test", "email": "test@example.com", "password": "123456"})
assert response.status_code == 200
assert response.json()["data"]["email"] == "test@example.com"
13. π Running in Production
Use Uvicorn with Gunicorn:
pip install gunicorn
gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app
Use environment variables, .env
, and tools like python-dotenv
.
14. π Documentation & OpenAPI
FastAPI automatically generates:
-
/docs
β Swagger UI -
/redoc
β ReDoc -
/openapi.json
β OpenAPI schema
Customize via:
FastAPI(
title="My App",
description="API for My Application",
version="1.0.0",
docs_url="/documentation",
redoc_url=None
)
15. β Conclusion
FastAPI is a production-ready, robust, and efficient Python web framework that scales well with modern microservice-based and async-first architectures.
Key Advantages:
- Automatic docs
- Pydantic-based validation
- Async support
- Easy to test and scale
- Secure and extensible
Top comments (0)