Dependencies - Sub-dependencies
Learn how to create dependencies that have sub-dependencies for arbitrarily deep dependency graphs.
🎯 What You'll Learn
- •Create dependencies that depend on other dependencies
- •Understand how FastAPI resolves dependency chains
- •Build arbitrarily nested dependency graphs
- •Learn how FastAPI caches dependency results
Dependencies - Sub-dependencies
🎯 What You'll Learn
- Create dependencies that have sub-dependencies
- Understand how FastAPI resolves dependency chains automatically
- Build arbitrarily nested dependency graphs
- Learn how FastAPI caches dependency results to avoid multiple calls
📚 Theory
You can create dependencies that have sub-dependencies.
They can be as deep as you need them to be.
FastAPI will take care of solving them.
First Dependency "Dependable"
You could create a first dependency ("dependable") like:
def query_extractor(q: str | None = None):
return q
It declares an optional query parameter q as a str, and then it just returns it.
This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
Second Dependency, "Dependable" and "Dependant"
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
def query_or_cookie_extractor(
q: Annotated[str, Depends(query_extractor)],
last_query: Annotated[str | None, Cookie()] = None,
):
if not q:
return last_query
return q
Let's focus on the parameters declared:
- Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
- It depends on the
query_extractor, and assigns the value returned by it to the parameterq.
- It depends on the
- It also declares an optional
last_querycookie, as astr.- If the user didn't provide any query
q, we use the last query used, which we saved to a cookie before.
- If the user didn't provide any query
Use the Dependency
Then we can use the dependency with:
@app.get("/items/")
async def read_query(
query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
):
return {"q_or_cookie": query_or_default}
Notice that we are only declaring one dependency in the path operation function, the query_or_cookie_extractor.
But FastAPI will know that it has to solve query_extractor first, to pass the results of that to query_or_cookie_extractor while calling it.
Using the Same Dependency Multiple Times
If one of your dependencies is declared multiple times for the same path operation, for example, multiple dependencies have a common sub-dependency, FastAPI will know to call that sub-dependency only once per request.
🔧 Key Concepts
- Dependable: A function that can be used as a dependency
- Dependant: A function that depends on other dependencies
- Dependency Chain: A series of dependencies where each depends on the previous one
- Dependency Caching: FastAPI's optimization to avoid calling the same dependency multiple times
💡 Best Practices
- Use sub-dependencies to break complex logic into smaller, testable pieces
- Take advantage of automatic caching for expensive operations
- Use
use_cache=Falseonly when you specifically need fresh values on each call - Keep dependency functions focused on a single responsibility
🔗 Additional Resources
💡 Hint
Remember that sub-dependencies are resolved automatically by FastAPI - you only need to declare the top-level dependency in your path operation.
Ready to Practice?
Now that you understand the theory, let's put it into practice with hands-on coding!
Start Interactive Lesson