Docs

README

๐Ÿ“‹ Task Management API

A complete REST API project demonstrating FastAPI, SQLAlchemy, JWT authentication, and Docker deployment.

๐ŸŽฏ Learning Objectives

After working through this project, you'll understand:

  • โ€ขFastAPI Framework - Building modern Python APIs with automatic documentation
  • โ€ขSQLAlchemy ORM - Database modeling with Python objects
  • โ€ขJWT Authentication - Secure token-based authentication
  • โ€ขPydantic Validation - Request/response data validation with type hints
  • โ€ขDependency Injection - FastAPI's DI system for clean, testable code
  • โ€ขDocker Deployment - Containerizing and deploying Python applications

Features

  • โ€ขUser registration and login with JWT tokens
  • โ€ขFull CRUD operations for tasks
  • โ€ขTask categories, priorities, and due dates
  • โ€ขFiltering and pagination
  • โ€ขTask completion statistics
  • โ€ขPostgreSQL database (SQLite for development)
  • โ€ขDocker Compose for production
  • โ€ขComprehensive test suite

๐Ÿš€ Quick Start

Option 1: Local Development (Recommended for Learning)

cd 01_task_api

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # Linux/Mac
# .venv\Scripts\activate   # Windows

# Install dependencies
pip install -r requirements.txt

# Run the API
uvicorn app.main:app --reload

Option 2: Docker Compose (Production-like)

cd 01_task_api
docker-compose up -d

Access the API

๐Ÿ“š API Endpoints

Authentication

MethodEndpointDescription
POST/api/users/registerRegister a new user
POST/api/users/loginLogin and get JWT token
GET/api/users/meGet current user profile
DELETE/api/users/meDelete current user account

Tasks (Authenticated)

MethodEndpointDescription
POST/api/tasks/Create a new task
GET/api/tasks/List all tasks (with filters)
GET/api/tasks/{id}Get specific task
PUT/api/tasks/{id}Update task
DELETE/api/tasks/{id}Delete task
PATCH/api/tasks/{id}/completeMark task complete
GET/api/tasks/stats/summaryGet task statistics

Query Parameters for GET /api/tasks/

  • โ€ขskip - Pagination offset (default: 0)
  • โ€ขlimit - Items per page (default: 100, max: 100)
  • โ€ขcompleted - Filter by status (true/false)
  • โ€ขpriority - Filter by priority (low/medium/high/urgent)
  • โ€ขcategory - Filter by category name

๐Ÿ’ก Usage Examples

Register a User

curl -X POST http://localhost:8000/api/users/register \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "username": "myuser", "password": "mypassword123"}'

Login and Get Token

curl -X POST http://localhost:8000/api/users/login \
  -d "username=myuser&password=mypassword123"

# Response: {"access_token": "eyJ...", "token_type": "bearer"}

Create a Task

curl -X POST http://localhost:8000/api/tasks/ \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Learn FastAPI",
    "description": "Complete the tutorial",
    "priority": "high",
    "category": "learning"
  }'

List Tasks with Filters

# Get high priority incomplete tasks
curl -X GET "http://localhost:8000/api/tasks/?completed=false&priority=high" \
  -H "Authorization: Bearer YOUR_TOKEN"

๐Ÿ“ Project Structure

01_task_api/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ __init__.py       # Package marker
โ”‚   โ”œโ”€โ”€ main.py           # FastAPI application entry point
โ”‚   โ”œโ”€โ”€ config.py         # Settings with pydantic-settings
โ”‚   โ”œโ”€โ”€ database.py       # SQLAlchemy engine and session
โ”‚   โ”œโ”€โ”€ models.py         # ORM models (User, Task)
โ”‚   โ”œโ”€โ”€ schemas.py        # Pydantic request/response models
โ”‚   โ”œโ”€โ”€ auth.py           # JWT authentication utilities
โ”‚   โ””โ”€โ”€ routers/
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ”œโ”€โ”€ users.py      # User registration, login, profile
โ”‚       โ””โ”€โ”€ tasks.py      # Task CRUD operations
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ conftest.py       # Test fixtures
โ”‚   โ””โ”€โ”€ test_api.py       # API tests
โ”œโ”€โ”€ Dockerfile            # Container definition
โ”œโ”€โ”€ docker-compose.yml    # Multi-container setup
โ”œโ”€โ”€ requirements.txt      # Python dependencies
โ””โ”€โ”€ README.md

๐Ÿ”‘ Key Concepts Explained

FastAPI Application Setup

from fastapi import FastAPI
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Startup and shutdown events."""
    # Startup: Create database tables
    Base.metadata.create_all(bind=engine)
    yield
    # Shutdown: Cleanup if needed

app = FastAPI(
    title="Task Management API",
    lifespan=lifespan
)

Dependency Injection

from fastapi import Depends
from sqlalchemy.orm import Session

def get_db():
    """Database session dependency."""
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/tasks/")
def get_tasks(
    db: Session = Depends(get_db),              # Database session
    user: User = Depends(get_current_user),     # Authenticated user
    skip: int = 0,                               # Query parameter
    limit: int = 100
):
    return db.query(Task).filter(Task.owner_id == user.id).all()

JWT Authentication Flow

# 1. User logs in with username/password
# 2. Server validates credentials
# 3. Server creates JWT token with user info
# 4. Client stores token and sends with each request
# 5. Server validates token and extracts user

def create_access_token(data: dict) -> str:
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(minutes=30)
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")

Pydantic Schema Validation

from pydantic import BaseModel, Field, EmailStr

class TaskCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=200)
    description: str | None = Field(None, max_length=1000)
    priority: TaskPriority = TaskPriority.MEDIUM

# Automatic validation on request:
# - title is required (...)
# - title length between 1-200 chars
# - description is optional, max 1000 chars
# - priority defaults to MEDIUM

๐Ÿงช Running Tests

# Install test dependencies
pip install pytest pytest-asyncio httpx

# Run all tests
pytest tests/ -v

# Run with coverage
pip install pytest-cov
pytest tests/ --cov=app --cov-report=html

๐Ÿ”ง Configuration

Environment variables (use .env file):

# Database (SQLite by default, PostgreSQL for production)
DATABASE_URL=sqlite:///./tasks.db
# DATABASE_URL=postgresql://user:pass@localhost:5432/tasks

# JWT Settings
SECRET_KEY=your-super-secret-key-change-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# App Settings
DEBUG=true

๐Ÿ“ˆ Extending the API

Add a New Model

  1. โ€ขCreate model in models.py:
class Category(Base):
    __tablename__ = "categories"
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
  1. โ€ขAdd schemas in schemas.py
  2. โ€ขCreate router in routers/categories.py
  3. โ€ขRegister router in main.py

Add Pagination Response

from math import ceil

class PaginatedTasks(BaseModel):
    items: list[TaskResponse]
    total: int
    page: int
    per_page: int
    pages: int

@router.get("/", response_model=PaginatedTasks)
def list_tasks(page: int = 1, per_page: int = 20):
    total = db.query(Task).count()
    items = db.query(Task).offset((page-1)*per_page).limit(per_page).all()
    return {
        "items": items,
        "total": total,
        "page": page,
        "per_page": per_page,
        "pages": ceil(total / per_page)
    }

๐Ÿ“š Related Learning

โœ… Project Checklist

  • โ€ข Run the API and explore /docs
  • โ€ข Register a user and login
  • โ€ข Create, update, and delete tasks
  • โ€ข Try filtering tasks by priority and status
  • โ€ข Run the test suite
  • โ€ข Add a new field to tasks (e.g., tags)
  • โ€ข Deploy with Docker Compose
  • โ€ข Add rate limiting middleware
README - Python Tutorial | DeepML