Dependency Injection in FastAPI with Depends
FastAPI's Depends lets endpoints declare what they need (a database session, the current user, pagination settings) and FastAPI provides it. Dependencies can depend on other dependencies, and they're easy to replace in tests.
A simple dependency
from typing import Annotated
from fastapi import Depends, Query
class Pagination:
def __init__(self, page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100)):
self.offset = (page - 1) * size
self.limit = size
Paging = Annotated[Pagination, Depends()]
@app.get("/articles")
async def list_articles(paging: Paging):
return await articles.list(offset=paging.offset, limit=paging.limit)
Dependencies with cleanup (yield)
from sqlalchemy.ext.asyncio import AsyncSession
async def get_db():
async with SessionLocal() as session:
yield session # the endpoint runs here
# session is closed after the response
DbSession = Annotated[AsyncSession, Depends(get_db)]
Chaining: the current user
from fastapi import HTTPException, status
from fastapi.security import OAuth2PasswordBearer
oauth2 = OAuth2PasswordBearer(tokenUrl="/auth/token")
async def get_current_user(token: Annotated[str, Depends(oauth2)], db: DbSession):
user = await users.from_token(db, token)
if not user:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
return user
CurrentUser = Annotated[User, Depends(get_current_user)]
async def require_admin(user: CurrentUser):
if user.role != "admin":
raise HTTPException(status.HTTP_403_FORBIDDEN, "Admins only")
return user
@app.delete("/articles/{article_id}", dependencies=[Depends(require_admin)])
async def delete_article(article_id: int, db: DbSession): ...
Why this design works well
- Endpoints read like a list of requirements.
- Within one request, the same dependency is evaluated once and shared.
Annotatedaliases (DbSession,CurrentUser) keep signatures short.- Tests swap implementations with
app.dependency_overrides.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.