Thursday, 20 November 2025

Diagnosis for running all Scripts

 Great — here is the complete ready-to-run folder structure for all 12 FastAPI modules, including:

__init__.py (so Python treats folders as packages)
main.py for every module
✅ A root-level requirements.txt
✅ Windows (.bat) and Linux/Mac (.sh) run scripts
✅ A unified recommended project layout

If you want, I can also fill every module with full working code exactly matching the 12-hour tutorial content.


FASTAPI 12-Module Project — Full Folder Structure

fastapi-12hr/
│
├── requirements.txt
├── run_module.bat
├── run_module.sh
├── README.md
│
├── module1/
│   ├── __init__.py
│   └── main.py
│
├── module2/
│   ├── __init__.py
│   └── main.py
│
├── module3/
│   ├── __init__.py
│   └── main.py
│
├── module4/
│   ├── __init__.py
│   └── main.py
│
├── module5/
│   ├── __init__.py
│   └── main.py
│
├── module6/
│   ├── __init__.py
│   ├── main.py
│   ├── models.py
│   └── db_init.py
│
├── module7/
│   ├── __init__.py
│   ├── main.py
│   ├── auth.py
│   └── users.py
│
├── module8/
│   ├── __init__.py
│   └── main.py
│
├── module9/
│   ├── __init__.py
│   ├── main.py
│   └── test_main.py
│
├── module10/
│   ├── __init__.py
│   └── main.py
│
├── module11/
│   ├── __init__.py
│   ├── main.py
│   ├── models.py
│   ├── schemas.py
│   ├── crud.py
│   └── auth.py
│
└── module12/
    ├── __init__.py
    └── main.py

📌 Root Files

requirements.txt

fastapi
uvicorn[standard]
pydantic
sqlmodel
sqlalchemy
aiosqlite
python-jose[bcrypt]
passlib[bcrypt]
pytest
httpx

run_module.bat (Windows)

@echo off
SET MODULE=%1

IF "%MODULE%"=="" (
    echo Usage: run_module module2
    exit /b
)

uvicorn %MODULE%.main:app --reload

Usage:

run_module module2

run_module.sh (Linux / macOS)

#!/bin/bash

MODULE=$1

if [ -z "$MODULE" ]; then
    echo "Usage: ./run_module.sh module2"
    exit 1
fi

uvicorn $MODULE.main:app --reload

Make executable:

chmod +x run_module.sh

Run:

./run_module.sh module2

📌 Starter Code for Each Module

Below is minimal working code for every module.
I can replace each one with full detailed code from the tutorial if you want.


module1/main.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"message": "Hello, FastAPI Module 1!"}

module2/main.py

(Your original module — fixed)

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    tags: list[str] = []

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

@app.post("/items/")
def create_item(item: Item):
    return {"created": item}

module3/main.py

from fastapi import FastAPI
from pydantic import BaseModel, validator

app = FastAPI()

class User(BaseModel):
    username: str
    age: int

    @validator("age")
    def validate_age(cls, v):
        if v <= 0:
            raise ValueError("Age must be positive")
        return v

@app.post("/user")
def add_user(user: User):
    return user

🧱 I won’t paste all modules unless you request it (to avoid making this message too long).


FASTAPI — 12‑Hour Hands‑On Tutorial (12 Modules) — FULL CODE

This document contains the 12‑module tutorial with full starter code for every module. Each module includes a working main.py and any supporting files required to run the example. Use the root requirements.txt and the provided run_module.sh / run_module.bat to run any module.


Project layout (ready)

fastapi-12hr/
requirements.txt
run_module.sh
run_module.bat
README.md
module1/
__init__.py
main.py
module2/
__init__.py
main.py
module3/
__init__.py
main.py
module4/
__init__.py
main.py
module5/
__init__.py
main.py
module6/
__init__.py
main.py
models.py
db_init.py
module7/
__init__.py
main.py
auth.py
users.py
module8/
__init__.py
main.py
module9/
__init__.py
main.py
test_main.py
module10/
__init__.py
main.py
module11/
__init__.py
main.py
models.py
schemas.py
crud.py
auth.py
module12/
__init__.py
main.py

requirements.txt

fastapi
uvicorn[standard]
pydantic
sqlmodel
sqlalchemy
aiosqlite
python-jose[bcrypt]
passlib[bcrypt]
pytest
httpx

run_module.sh

#!/bin/bash
MODULE=$1
if [ -z "$MODULE" ]; then
echo "Usage: ./run_module.sh module2"
exit 1
fi
uvicorn $MODULE.main:app --reload

Make executable: chmod +x run_module.sh


run_module.bat

@echo off
SET MODULE=%1
IF "%MODULE%"=="" (
echo Usage: run_module module2
exit /b
)
uvicorn %MODULE%.main:app --reload

Module code (full)

Note: For each module you can run ./run_module.sh moduleX (or run_module moduleX on Windows) from the repository root.


module1 — Basics

module1/main.py

from fastapi import FastAPI

app = FastAPI(
title="Module 1 - FastAPI Basics",
description="Simple hello world",
version="0.1",
)

@app.get("/", summary="Root endpoint")
def read_root():
return {"message": "Hello, FastAPI Module 1!"}

module2 — Path params, query params, request body

module2/main.py

from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional

app = FastAPI(title="Module 2 - Params & Body")

class Item(BaseModel):
name: str
price: float
tags: List[str] = []

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
"""Path param `item_id` and optional query param `q`"""
return {"item_id": item_id, "q": q}

@app.post("/items/")
def create_item(item: Item):
"""Receive JSON body validated by Pydantic"""
# Returning `item` directly will be serialized to JSON
return {"created": item}

module3 — Data validation with Pydantic

module3/main.py

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr, validator
from typing import List

app = FastAPI(title="Module 3 - Pydantic")

class User(BaseModel):
username: str
email: EmailStr
age: int

@validator("age")
def age_must_be_positive(cls, v):
if v < 0:
raise ValueError("age must be positive")
return v

class Group(BaseModel):
name: str
members: List[User]

@app.post("/groups/")
def create_group(group: Group):
return {"group": group}

module4 — Dependency injection & simple API key security

module4/main.py

from fastapi import FastAPI, Depends, HTTPException, Header
from typing import Optional

app = FastAPI(title="Module 4 - Dependencies & Security")

async def get_api_key(x_api_key: Optional[str] = Header(None)):
if x_api_key != "secret123":
raise HTTPException(status_code=401, detail="Unauthorized")
return x_api_key

@app.get("/secure")
async def secure_endpoint(api_key: str = Depends(get_api_key)):
return {"message": "Secure data", "api_key": api_key}

# Example of injecting a simple resource (like DB session placeholder)
async def get_db():
# yield a fake resource; replace with real DB session in later modules
yield {"db": "fake-session"}

@app.get("/use-db")
async def use_db(db = Depends(get_db)):
return {"using": db}

module5 — Background tasks, startup/shutdown events, middleware

module5/main.py

from fastapi import FastAPI, BackgroundTasks, Request
import time

app = FastAPI(title="Module 5 - Background & Middleware")

@app.on_event("startup")
def startup():
print("[startup] App is starting")

@app.on_event("shutdown")
def shutdown():
print("[shutdown] App is shutting down")

def write_log(message: str):
with open("module5.log", "a", encoding="utf-8") as f:
f.write(message + "
")

@app.post("/notify")
def notify(background_tasks: BackgroundTasks, msg: str):
background_tasks.add_task(write_log, msg)
return {"status": "scheduled"}

# Simple middleware to log path and duration
@app.middleware("http")
async def log_middleware(request: Request, call_next):
start = time.time()
response = await call_next(request)
duration = time.time() - start
with open("module5_requests.log", "a", encoding="utf-8") as f:
f.write(f"{request.method} {request.url.path} {duration:.4f}s
")
return response

module6 — Database integration (SQLModel + SQLite)

module6/models.py

from sqlmodel import SQLModel, Field
from typing import Optional

class Todo(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
title: str
done: bool = False

module6/db_init.py

from sqlmodel import create_engine, SQLModel
from .models import Todo

sqlite_url = "sqlite:///./module6_todos.db"
engine = create_engine(sqlite_url, echo=False)

def init_db():
SQLModel.metadata.create_all(engine)

module6/main.py

from fastapi import FastAPI, HTTPException
from sqlmodel import Session, select
from .models import Todo
from .db_init import engine, init_db

app = FastAPI(title="Module 6 - SQLModel (SQLite)")
init_db()

@app.post('/todos/')
def create_todo(todo: Todo):
with Session(engine) as session:
session.add(todo)
session.commit()
session.refresh(todo)
return todo

@app.get('/todos/')
def list_todos():
with Session(engine) as session:
todos = session.exec(select(Todo)).all()
return todos

@app.get('/todos/{todo_id}')
def get_todo(todo_id: int):
with Session(engine) as session:
todo = session.get(Todo, todo_id)
if not todo:
raise HTTPException(status_code=404, detail='Not found')
return todo

@app.put('/todos/{todo_id}')
def update_todo(todo_id: int, updated: Todo):
with Session(engine) as session:
todo = session.get(Todo, todo_id)
if not todo:
raise HTTPException(status_code=404, detail='Not found')
todo.title = updated.title
todo.done = updated.done
session.add(todo)
session.commit()
session.refresh(todo)
return todo

@app.delete('/todos/{todo_id}')
def delete_todo(todo_id: int):
with Session(engine) as session:
todo = session.get(Todo, todo_id)
if not todo:
raise HTTPException(status_code=404, detail='Not found')
session.delete(todo)
session.commit()
return {"deleted": todo_id}

module7 — Authentication (OAuth2 password flow + JWT sketch)

module7/users.py

# simple in-memory user store (for demo only)
users_db = {
"alice": {
"username": "alice",
"full_name": "Alice Example",
"email": "alice@example.com",
"hashed_password": "$2b$12$KIX0...", # replace with real bcrypt hash
"disabled": False,
}
}

module7/auth.py

from datetime import datetime, timedelta
from jose import jwt
from passlib.context import CryptContext

SECRET_KEY = "CHANGE_THIS_SECRET"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

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 = 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

module7/main.py

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from .users import users_db
from .auth import verify_password, create_access_token
from datetime import timedelta

app = FastAPI(title="Module 7 - Auth (JWT)")

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.post('/token')
def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = users_db.get(form_data.username)
if not user:
raise HTTPException(status_code=400, detail='Incorrect username or password')
# NOTE: hashed_password should be real bcrypt hash; for demo assume verify_password returns True
if not verify_password(form_data.password, user.get('hashed_password', '')):
raise HTTPException(status_code=400, detail='Incorrect username or password')
access_token_expires = timedelta(minutes=30)
access_token = create_access_token(data={"sub": user['username']}, expires_delta=access_token_expires)
return {"access_token": access_token, "token_type": "bearer"}

@app.get('/protected')
def protected_route(token: str = Depends(oauth2_scheme)):
return {"token": token}

Note: This module uses a simplified in-memory store and a placeholder bcrypt hash. For real apps, use a DB and properly hash passwords.


module8 — File uploads & streaming


No comments:

Post a Comment

Diagnosis for running all Scripts

 Great — here is the complete ready-to-run folder structure for all 12 FastAPI modules , including: ✅ __init__.py (so Python treats folder...