Python for JS Devs · FastAPI
Depends() is FastAPI's answer to Express middleware — but composable, typed, testable, and self-documenting.
In Express you thread shared concerns (DB handle, auth, config) through middleware and req. FastAPI inverts it: a route declares what it needs as a parameter, and FastAPI provides it. That's dependency injection.
from fastapi import Depends
def pagination(skip: int = 0, limit: int = 20) -> dict:
return {"skip": skip, "limit": limit}
@app.get("/items")
def list_items(page: dict = Depends(pagination)):
return page # {"skip": 0, "limit": 20}, from ?skip=&limit=
FastAPI runs pagination, validates its params from the request too, and injects the result. Dependencies can depend on dependencies — they compose into a tree.
yield pattern: setup + teardownA dependency that yields gives a resource to the route, then runs cleanup after the response — the analogue of middleware that wraps next(). This is the way to provide a DB session:
def get_db():
db = SessionLocal()
try:
yield db # hand the session to the route
finally:
db.close() # always cleanup after response
@app.get("/users/{uid}")
def get_user(uid: int, db = Depends(get_db)):
return db.get(User, uid)
from fastapi import Header, HTTPException
def current_user(authorization: str = Header()):
user = verify_token(authorization)
if user is None:
raise HTTPException(status_code=401, detail="Not authenticated")
return user
@app.get("/me")
def me(user = Depends(current_user)):
return user
/docs), reusable (share current_user across routes), and testable (override it with app.dependency_overrides in tests — no monkeypatching the request object). It also short-circuits with a clean 401 before your handler even runs.
Write the pagination dependency and inject it into a /items route; confirm ?skip=5&limit=2 flows through /docs. Then sketch a current_user dependency that raises 401 when a fake header is missing. Seeing shared logic injected — not copy-pasted — is the win.
Depends(...) — usually a plain function.yield lets you:yield (in finally) runs post-response — perfect for closing a DB session.app.dependency_overrides swaps real deps (DB, auth) for fakes — no monkeypatching needed.dependencies=[...] pattern.