Discover how a simple class can save you from repeating the same setup code everywhere!
Why Class-based dependencies in FastAPI? - Purpose & Use Cases
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine building a web app where you need to share the same setup code, like database connections or user authentication, across many routes. You write the same code again and again inside each route function.
This manual repetition makes your code bulky and hard to maintain. If you want to change the setup, you must update every route. It's easy to make mistakes and forget some places, causing bugs and inconsistent behavior.
Class-based dependencies let you wrap shared setup logic inside a class. FastAPI creates and reuses this class automatically for your routes. This keeps your code clean, reusable, and easy to update in one place.
def get_db(): db = connect_db() try: yield db finally: db.close() @app.get('/items') async def read_items(db=Depends(get_db)): return db.query_items()
class DBSession: def __init__(self): self.db = connect_db() def __call__(self): try: yield self.db finally: self.db.close() @app.get('/items') async def read_items(db=Depends(DBSession())): return db.query_items()
This lets you organize complex setup steps cleanly and reuse them effortlessly across your app's routes.
Think of a library where every book needs a card catalog entry. Instead of writing the catalog entry steps for each book, you create a reusable card catalog class that handles it for all books automatically.
Manual setup code repetition is error-prone and hard to maintain.
Class-based dependencies wrap shared logic in one reusable place.
FastAPI manages these classes to keep your routes clean and consistent.
Practice
Solution
Step 1: Understand the role of class-based dependencies
Class-based dependencies allow grouping related logic inside a class, making code cleaner and reusable.Step 2: Compare options with this purpose
Only To group related dependency logic in one reusable place correctly describes grouping related logic; others describe unrelated features.Final Answer:
To group related dependency logic in one reusable place -> Option CQuick Check:
Class-based dependencies = Group logic [OK]
- Thinking class dependencies replace route functions
- Assuming they auto-generate HTML
- Believing they only handle databases
Solution
Step 1: Recall FastAPI dependency requirements
FastAPI requires the class to be callable, which means it must implement the __call__ method.Step 2: Match method names to this requirement
Only __call__ makes the class instance callable; __init__ is for initialization, others are invalid.Final Answer:
__call__ -> Option BQuick Check:
Callable class = __call__ method [OK]
- Choosing __init__ instead of __call__
- Using random method names like 'run'
- Confusing dependency with method name
from fastapi import FastAPI, Depends
app = FastAPI()
class Greeting:
def __init__(self, name: str = "Guest"):
self.name = name
def __call__(self):
return f"Hello, {self.name}!"
@app.get("/hello")
async def hello(greet: str = Depends(Greeting)):
return {"message": greet}Solution
Step 1: Analyze the Greeting class behavior
The class sets name to "Guest" by default and __call__ returns "Hello, Guest!" string.Step 2: Understand dependency injection in endpoint
Depends(Greeting) creates an instance with default name, so greet is "Hello, Guest!" string.Final Answer:
{"message": "Hello, Guest!"} -> Option DQuick Check:
Default name used = Hello, Guest! [OK]
- Expecting 'name' literal instead of variable value
- Assuming runtime error without cause
- Ignoring default parameter in __init__
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
@app.get("/count")
async def get_count(counter: Counter = Depends(Counter)):
counter.increment()
return {"count": counter.count}Solution
Step 1: Trace the dependency execution flow
Depends(Counter) creates a new instance each request; self.count = 0, increment() sets to 1, returns {"count": 1}. Count resets every request.Step 2: Pinpoint the logical error
self.count is an instance attribute (per-request); for persistent counting across requests, count must be a class attribute.Final Answer:
count attribute should be a class variable -> Option AQuick Check:
Instance attr = resets per request [OK]
- Thinking Depends can't accept classes
- Assuming async needed for increment
- Confusing instance and class variables
class UserInfo:
def __init__(self, user_id: int):
self.user_id = user_id
def __call__(self):
return f"User ID is {self.user_id}"
@app.get("/user")
async def user(info: str = Depends(UserInfo)):
return {"info": info}Choose the correct way to pass
user_id from query parameters.Solution
Step 1: Understand how FastAPI injects parameters
FastAPI injects parameters into __init__ if they have default values with Query or Body.Step 2: Use Query to declare user_id in __init__
Adding user_id: int = Query(...) in __init__ allows FastAPI to get it from query parameters.Final Answer:
Use __init__(self, user_id: int = Query(...)) and import Query -> Option AQuick Check:
Query param in __init__ = dynamic dependency [OK]
- Trying to pass parameters in __call__
- Passing instance in Depends directly
- Using global variables instead of parameters
