Python for JS Devs · Reference

FastAPI cheat sheet

The patterns you reach for daily. Source: fastapi.tiangolo.com.

Minimal app + run

from fastapi import FastAPI
app = FastAPI()

@app.get("/")
def root():
    return {"ok": True}

# uv run uvicorn main:app --reload
# docs at /docs

Params: path / query / body

@app.put("/users/{uid}")
def update(uid: int,          # path
           notify: bool = False,  # query
           body: UserUpdate):     # body (model)
    ...

Pydantic models (v2)

from pydantic import BaseModel, EmailStr, Field

class UserIn(BaseModel):
    email: EmailStr
    name: str = Field(min_length=2)  # not min!

class UserOut(BaseModel):
    id: int
    email: EmailStr
    # no password_hash → stripped

Response model + status

@app.post("/users",
    response_model=UserOut,
    status_code=201)
def create(payload: UserIn):
    ...

Dependency injection

from fastapi import Depends

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/x")
def h(db = Depends(get_db)): ...

Errors & status codes

from fastapi import HTTPException
raise HTTPException(404, "Not found")
# 201 created · 401 auth · 403 forbidden
# 404 missing · 409 conflict · 422 invalid

Routers (structure)

# routers/users.py
router = APIRouter(prefix="/users",
                   tags=["users"])
@router.get("/{uid}")
def get(uid: int): ...

# main.py
app.include_router(users.router)

Settings (env)

from pydantic_settings import BaseSettings
class Settings(BaseSettings):
    database_url: str
    model_config = {"env_file": ".env"}
settings = Settings()

async def vs def (the rule)

# awaits async libs → async def
# sync/blocking I/O  → def (threadpooled)
# NEVER: async def + blocking call
#        (freezes the event loop)

Async LLM call

client = anthropic.AsyncAnthropic()

@app.post("/chat")
async def chat(b: ChatIn):
    m = await client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        messages=[{"role":"user",
                   "content": b.message}])
    return {"reply": m.content[0].text}

Streaming (async generator)

from fastapi.responses import StreamingResponse

async def gen(msg):
    async with client.messages.stream(...) as s:
        async for t in s.text_stream:
            yield t

@app.post("/stream")
async def stream(b: ChatIn):
    return StreamingResponse(gen(b.message),
        media_type="text/plain")

SQLAlchemy 2.0 (typed)

class Base(DeclarativeBase): pass
class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(
        primary_key=True)
    email: Mapped[str]

stmt = select(User).where(User.email == e)
user = db.scalars(stmt).first()