In the previous chapter, OpenAPI Schema Generation, we saw how FastAPI automatically documents your API. Now, we are going to look at how to clean up your code, make it reusable, and handle shared logic efficiently.
Welcome to Dependency Injection, arguably the most powerful feature in FastAPI.
Imagine you are writing a route to get the current user's profile. Your function has to:
If you have 50 routes that need user authentication, you have to copy-paste steps 1-4 fifty times. If you change how tokens work, you have to edit 50 files. This is a maintenance nightmare.
Think of your route function as a CEO. The CEO shouldn't be making coffee or finding pens. The CEO should just say "I need a pen," and start writing.
Dependency Injection is your Personal Assistant.
Depends).
Let's use a simple example: Pagination. Many routes need to handle skip and limit query parameters. Instead of repeating them, let's create a dependency.
A dependency is just a standard Python function. It can accept parameters (like Query or Path parameters we learned in Request Parameters and Validation).
async def pagination_params(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
Explanation:
@app.get).skip and limit in the URL."
Now, we tell our route to use this logic using Depends.
from fastapi import FastAPI, Depends
app = FastAPI()
@app.get("/items/")
async def list_items(params: dict = Depends(pagination_params)):
return params
Explanation:
Depends.params.Depends(pagination_params) tells FastAPI: "Before running list_items, run pagination_params first, and give me the result."
If a user visits /items/?skip=20&limit=50:
list_items needs pagination_params.pagination_params(skip=20, limit=50).{"skip": 20, "limit": 50}.list_items(params={...}).Dependencies can have their own dependencies. FastAPI resolves this "graph" automatically.
Imagine a kitchen:
def shopper():
return "Groceries"
def ingredients(data: str = Depends(shopper)):
return f"Chopped {data}"
@app.get("/cook")
async def cook_meal(food: str = Depends(ingredients)):
return {"meal": f"Cooked {food}"}
Explanation:
/cook, FastAPI figures out the chain:shopper() -> gets "Groceries".ingredients("Groceries") -> gets "Chopped Groceries".cook_meal("Chopped Groceries").You didn't have to manage this chain manually. FastAPI did the "plumbing" for you.
How does FastAPI know what to run and in what order? It uses a system called Topological Sort to resolve the dependency graph.
When a request arrives, FastAPI doesn't just run your function. It builds a stack of tasks.
solve_dependencies
The magic happens in fastapi/dependencies/utils.py. The core function is solve_dependencies.
When you start your app (as described in The FastAPI App Instance), FastAPI analyzes all your functions. When a request comes in, it executes this logic:
# Simplified concept from fastapi/dependencies/utils.py
async def solve_dependencies(request, dependant):
values = {}
# Loop through everything the route "Depends" on
for sub_dep in dependant.dependencies:
# RECURSION: Solve sub-dependencies first
sub_result = await solve_dependencies(request, sub_dep)
# Run the actual dependency function
call = sub_dep.call
solved = await call(**sub_result.values)
# Store the result
values[sub_dep.name] = solved
return values
Explanation:
call(...).values dictionary.
By default, Depends has a smart feature: use_cache=True.
If the same dependency is used multiple times in one request (e.g., getting the current_user for permission checks AND for logging), FastAPI runs it once and reuses the result.
# In fastapi/dependencies/models.py
@dataclass
class Dependant:
call: Callable[..., Any] | None = None
use_cache: bool = True # <--- Default is True
This prevents your API from doing unnecessary work, like hitting the database twice for the exact same user data in a single request.
The Dependency Injection system is the glue that holds a FastAPI application together.
This system is essentially a pipeline that prepares data for your function. In the next chapter, we will use this system to inject one of the most common requirements for any API: a Database Session.
Next Chapter: SQLModel Integration
Generated by Code IQ