FastAPI - Dependencies



The built-in dependency injection system of FastAPI makes it possible to integrate components easier when building your API. In programming, Dependency injection refers to the mechanism where an object receives other objects that it depends on. The other objects are called dependencies. Dependency injection has the following advantages −

  • reuse the same shared logic

  • share database connections

  • enforce authentication and security features

Assuming that a FastAPI app has two operation functions both having the same query parameters id, name and age.

from fastapi import FastAPI
app = FastAPI()
@app.get("/user/")
async def user(id: str, name: str, age: int):
   return {"id": id, "name": name, "age": age}
@app.get("/admin/")
async def admin(id: str, name: str, age: int):
   return {"id": id, "name": name, "age": age}

In case of any changes such as adding/removing query parameters, both the route decorators and functions need to be changed.

FastAPI provides Depends class and its object is used as a common parameter in such cases. First import Depends from FastAPI and define a function to receive these parameters −

async def dependency(id: str, name: str, age: int):
   return {"id": id, "name": name, "age": age}

Now we can use the return value of this function as a parameter in operation functions

@app.get("/user/")
async def user(dep: dict = Depends(dependency)):
   return dep

For each new Request, FastAPI calls the dependency function using the corresponding parameters, returns the result, and assigns the result to your operation.

You can use a class for managing dependencies instead of a function. Declare a class with id, name and age as attributes.

class dependency:
   def __init__(self, id: str, name: str, age: int):
      self.id = id
      self.name = name
      self.age = age 

Use this class as the type of parameters.

@app.get("/user/")
async def user(dep: dependency = Depends(dependency)):
   return dep
@app.get("/admin/")
async def admin(dep: dependency = Depends(dependency)):
   return dep 

Here, we used the dependency injection in the operation function. It can also be used as operation decoration. For example, we want to check if the value of query parameter age is less than 21. If yes it should throw an exception. So, we write a function to check it and use it as a dependency.

async def validate(dep: dependency = Depends(dependency)):
   if dep.age > 18:
      raise HTTPException(status_code=400, detail="You are not eligible")
@app.get("/user/", dependencies=[Depends(validate)])
async def user():
   return {"message": "You are eligible"}

In FastAPI dependency management, you can use yield instead of return to add some extra steps. For example, the following function uses database dependency with yield.

async def get_db():
   db = DBSession()
      try:
         yield db
      finally:
            db.close()
Advertisements