Dependencies¶
FastAPI has a very powerful but intuitiveDependency Injection system.
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components withFastAPI.
What is "Dependency Injection"¶
"Dependency Injection" means, in programming, that there is a way for your code (in this case, yourpath operation functions) to declare things that it requires to work and use: "dependencies".
And then, that system (in this caseFastAPI) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
This is very useful when you need to:
- Have shared logic (the same code logic again and again).
- Share database connections.
- Enforce security, authentication, role requirements, etc.
- And many other things...
All these, while minimizing code repetition.
First Steps¶
Let's see a very simple example. It will be so simple that it is not very useful, for now.
But this way we can focus on how theDependency Injection system works.
Create a dependency, or "dependable"¶
Let's first focus on the dependency.
It is just a function that can take all the same parameters that apath operation function can take:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:Annotated[dict,Depends(common_parameters)]):returncommons@app.get("/users/")asyncdefread_users(commons:Annotated[dict,Depends(common_parameters)]):returncommons🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:dict=Depends(common_parameters)):returncommons@app.get("/users/")asyncdefread_users(commons:dict=Depends(common_parameters)):returncommonsThat's it.
2 lines.
And it has the same shape and structure that all yourpath operation functions have.
You can think of it as apath operation function without the "decorator" (without the@app.get("/some-path")).
And it can return anything you want.
In this case, this dependency expects:
- An optional query parameter
qthat is astr. - An optional query parameter
skipthat is anint, and by default is0. - An optional query parameter
limitthat is anint, and by default is100.
And then it just returns adict containing those values.
Info
FastAPI added support forAnnotated (and started recommending it) in version 0.95.0.
If you have an older version, you would get errors when trying to useAnnotated.
Make sure youUpgrade the FastAPI version to at least 0.95.1 before usingAnnotated.
ImportDepends¶
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:Annotated[dict,Depends(common_parameters)]):returncommons@app.get("/users/")asyncdefread_users(commons:Annotated[dict,Depends(common_parameters)]):returncommons🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:dict=Depends(common_parameters)):returncommons@app.get("/users/")asyncdefread_users(commons:dict=Depends(common_parameters)):returncommonsDeclare the dependency, in the "dependant"¶
The same way you useBody,Query, etc. with yourpath operation function parameters, useDepends with a new parameter:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:Annotated[dict,Depends(common_parameters)]):returncommons@app.get("/users/")asyncdefread_users(commons:Annotated[dict,Depends(common_parameters)]):returncommons🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}@app.get("/items/")asyncdefread_items(commons:dict=Depends(common_parameters)):returncommons@app.get("/users/")asyncdefread_users(commons:dict=Depends(common_parameters)):returncommonsAlthough you useDepends in the parameters of your function the same way you useBody,Query, etc,Depends works a bit differently.
You only giveDepends a single parameter.
This parameter must be something like a function.
Youdon't call it directly (don't add the parenthesis at the end), you just pass it as a parameter toDepends().
And that function takes parameters in the same way thatpath operation functions do.
Tip
You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
Whenever a new request arrives,FastAPI will take care of:
- Calling your dependency ("dependable") function with the correct parameters.
- Get the result from your function.
- Assign that result to the parameter in yourpath operation function.
graph TBcommon_parameters(["common_parameters"])read_items["/items/"]read_users["/users/"]common_parameters --> read_itemscommon_parameters --> read_usersThis way you write shared code once andFastAPI takes care of calling it for yourpath operations.
Check
Notice that you don't have to create a special class and pass it somewhere toFastAPI to "register" it or anything similar.
You just pass it toDepends andFastAPI knows how to do the rest.
ShareAnnotated dependencies¶
In the examples above, you see that there's a tiny bit ofcode duplication.
When you need to use thecommon_parameters() dependency, you have to write the whole parameter with the type annotation andDepends():
commons:Annotated[dict,Depends(common_parameters)]But because we are usingAnnotated, we can store thatAnnotated value in a variable and use it in multiple places:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIapp=FastAPI()asyncdefcommon_parameters(q:str|None=None,skip:int=0,limit:int=100):return{"q":q,"skip":skip,"limit":limit}CommonsDep=Annotated[dict,Depends(common_parameters)]@app.get("/items/")asyncdefread_items(commons:CommonsDep):returncommons@app.get("/users/")asyncdefread_users(commons:CommonsDep):returncommonsTip
This is just standard Python, it's called a "type alias", it's actually not specific toFastAPI.
But becauseFastAPI is based on the Python standards, includingAnnotated, you can use this trick in your code. 😎
The dependencies will keep working as expected, and thebest part is that thetype information will be preserved, which means that your editor will be able to keep providing you withautocompletion,inline errors, etc. The same for other tools likemypy.
This will be especially useful when you use it in alarge code base where you usethe same dependencies over and over again inmanypath operations.
Toasync or not toasync¶
As dependencies will also be called byFastAPI (the same as yourpath operation functions), the same rules apply while defining your functions.
You can useasync def or normaldef.
And you can declare dependencies withasync def inside of normaldefpath operation functions, ordef dependencies inside ofasync defpath operation functions, etc.
It doesn't matter.FastAPI will know what to do.
Note
If you don't know, check theAsync:"In a hurry?" section aboutasync andawait in the docs.
Integrated with OpenAPI¶
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
So, the interactive docs will have all the information from these dependencies too:

Simple usage¶
If you look at it,path operation functions are declared to be used whenever apath andoperation matches, and thenFastAPI takes care of calling the function with the correct parameters, extracting the data from the request.
Actually, all (or most) of the web frameworks work in this same way.
You never call those functions directly. They are called by your framework (in this case,FastAPI).
With the Dependency Injection system, you can also tellFastAPI that yourpath operation function also "depends" on something else that should be executed before yourpath operation function, andFastAPI will take care of executing it and "injecting" the results.
Other common terms for this same idea of "dependency injection" are:
- resources
- providers
- services
- injectables
- components
FastAPI plug-ins¶
Integrations and "plug-ins" can be built using theDependency Injection system. But in fact, there is actuallyno need to create "plug-ins", as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to yourpath operation functions.
And dependencies can be created in a very simple and intuitive way that allows you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code,literally.
You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
FastAPI compatibility¶
The simplicity of the dependency injection system makesFastAPI compatible with:
- all the relational databases
- NoSQL databases
- external packages
- external APIs
- authentication and authorization systems
- API usage monitoring systems
- response data injection systems
- etc.
Simple and Powerful¶
Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
You can define dependencies that in turn can define dependencies themselves.
In the end, a hierarchical tree of dependencies is built, and theDependency Injection system takes care of solving all these dependencies for you (and their sub-dependencies) and providing (injecting) the results at each step.
For example, let's say you have 4 API endpoints (path operations):
/items/public//items/private//users/{user_id}/activate/items/pro/
then you could add different permission requirements for each of them just with dependencies and sub-dependencies:
graph TBcurrent_user(["current_user"])active_user(["active_user"])admin_user(["admin_user"])paying_user(["paying_user"])public["/items/public/"]private["/items/private/"]activate_user["/users/{user_id}/activate"]pro_items["/items/pro/"]current_user --> active_useractive_user --> admin_useractive_user --> paying_usercurrent_user --> publicactive_user --> privateadmin_user --> activate_userpaying_user --> pro_itemsIntegrated withOpenAPI¶
All these dependencies, while declaring their requirements, also add parameters, validations, etc. to yourpath operations.
FastAPI will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.







