Class-based dependencies help organize related logic in one place. They make your code cleaner and easier to reuse.
Class-based dependencies in FastAPI
Start learning this pattern below
Jump into concepts and practice - no test required
from fastapi import Depends, FastAPI app = FastAPI() class MyDependency: def __init__(self, param: str): self.param = param def __call__(self): return f"Value is {self.param}" @app.get("/items/") async def read_items(dep=Depends(MyDependency("example"))): return {"result": dep}
The class must implement the __call__ method to be used as a dependency.
You can pass parameters to the class constructor to customize the dependency.
from fastapi import Depends, FastAPI app = FastAPI() class CommonHeaders: def __init__(self, user_agent: str = "unknown"): self.user_agent = user_agent def __call__(self): return {"User-Agent": self.user_agent} @app.get("/headers") async def get_headers(headers=Depends(CommonHeaders("my-agent"))): return headers
from fastapi import Depends, FastAPI app = FastAPI() class Counter: def __init__(self): self.count = 0 def __call__(self): self.count += 1 return self.count @app.get("/count") async def get_count(counter=Depends(Counter())): return {"count": counter}
This program defines a class-based dependency that returns a greeting message. The route uses this dependency to greet the user named Alice.
from fastapi import FastAPI, Depends app = FastAPI() class Greeting: def __init__(self, name: str): self.name = name def __call__(self): return f"Hello, {self.name}!" @app.get("/greet") async def greet(greeting=Depends(Greeting("Alice"))): return {"message": greeting}
Class-based dependencies can hold state, but be careful with mutable state in async environments.
FastAPI creates a new instance of the class for each request by default.
You can combine class-based dependencies with other dependencies for flexible designs.
Class-based dependencies group related logic in one place.
They require a __call__ method to work as dependencies.
They help keep your FastAPI code clean and reusable.
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
