As FastAPI projects grow, code organization and reusability become increasingly important. While FastAPI’s dependency injection system is very flexible, you’ve probably noticed that many dependencies are simple functions. But did you know you can write dependency classes, too? In this article, I’ll show you how and why to use classes as dependencies for cleaner, testable, and more modular code.
Why Use Classes for Dependencies?
Dependency functions are quick to write but can get unwieldy as logic grows. With classes, your dependencies can:
- Bundle related logic and state
- Support configuration via
__init__
- Implement more complex patterns like context managers (for resource management)
- Make code more readable and testable
Basic Example: Dependency as a Class
Suppose you want a dependency that gets the current user from a JWT token and caches some computation across multiple dependency-injected calls in a single request.
from fastapi import Depends, HTTPException, Request
class UserDependency:
def __init__(self, request: Request):
self.request = request
self._user = None # Cache
async def __call__(self):
if self._user is not None:
return self._user
token = self.request.headers.get("Authorization")
if not token:
raise HTTPException(status_code=401, detail="No token provided.")
# ...parse and validate token, fetch user...
self._user = {"username": "fasteddy"} # Dummy user
return self._user
You can inject this class just like a function dependency:
@app.get("/me")
async def read_current_user(current_user=Depends(UserDependency)):
return current_user
When to Use Classes
- Dependencies with internal state or caching
- Sharing information/context between dependencies
- Implementing context managers (with
__enter__
/__exit__
or__aenter__
/__aexit__
) - Grouping related dependency logic and helper methods
Pro Tip: Dependency Classes Make Testing Easier
By using classes, you can mock dependencies more easily in your test suite:
from starlette.testclient import TestClient
class MockUserDependency:
async def __call__(self):
return {"username": "testuser"}
app.dependency_overrides[UserDependency] = MockUserDependency
Conclusion
Using classes as dependencies is a powerful design pattern in FastAPI that increases your code’s modularity and testability. Take a small refactor step today—your future refactoring-self will thank you.
Have you tried this pattern in your FastAPI code? Let me know on the site or in the comments!
— Fast Eddy
Leave a Reply