YouTip LogoYouTip

Fastapi Path Operation Dependencies

FastAPI provides a powerful and concise dependency injection system. Dependency injection is a design pattern that allows you to extract common logic (such as database connections, authentication, parameter validation, etc.) into reusable components, which can then be used in routes as needed. !(#) * * * ## What is Dependency Injection Simply put, a **dependency** is a function that can use the same parameters as path operation functions (query parameters, path parameters, request body, etc.). FastAPI will automatically call the dependency function before executing the route function and pass its return value to the route function. ## Example from typing import Annotated from fastapi import Depends, FastAPI app = FastAPI() # 1. Define dependency function def common_parameters(q: str | None=None, skip: int=0, limit: int=100): return{"q": q,"skip": skip,"limit": limit} # 2. Use dependency in route @app.get("/items/") async def read_items(commons: dict= Depends(common_parameters)): # commons receives the return value of the dependency function return commons @app.get("/users/") async def read_users(commons: dict= Depends(common_parameters)): # Multiple routes can reuse the same dependency return commons Code Explanation: | Part | Description | | --- | --- | | `common_parameters` | Dependency function for handling common query parameters | | `Depends(common_parameters)` | Declares that the value of parameter `commons` comes from the dependency function | | `commons: dict` | Receives the dictionary returned by the dependency function | > Both dependency functions and path operation functions use the same parameter declaration method. FastAPI will automatically parse the parameters of the dependency function. This means that dependency functions can also use query parameters, path parameters, request body, etc. * * * ## Execution Flow of Dependencies When a request arrives, the processing order in FastAPI: 1. Identify the route function and its dependencies 2. Execute dependency functions (in dependency order) 3. Pass the return value of the dependency function to the route function 4. Execute the route function * * * ## Using Classes as Dependencies Besides functions, you can also use classes as dependencies: ## Example from typing import Annotated from fastapi import Depends, FastAPI app = FastAPI() # Declare dependency using class class CommonQueryParams: def __init__ (self, q: str | None=None, skip: int=0, limit: int=100): self.q= q self.skip= skip self.limit= limit # Use class as dependency @app.get("/items/") async def read_items(commons: Annotated[CommonQueryParams, Depends()]): return{"q": commons.q,"skip": commons.skip,"limit": commons.limit} When `Depends()` is not passed any arguments, FastAPI will automatically use the type annotation of the parameter (`CommonQueryParams`) as the dependency. * * * ## Sub-dependencies Dependencies can have their own dependencies, forming a chain of dependencies: ## Example from typing import Annotated from fastapi import Depends, FastAPI app = FastAPI() # Dependency function def query_extractor(q: str | None=None): return q # Sub-dependency: depends on query_extractor def query_checker(q: str= Depends(query_extractor)): if q =="admin": # Sub-dependency can perform validation return q + " (checked)" return q # Route uses sub-dependency @app.get("/items/") async def read_items(q: str= Depends(query_checker)): return{"q": q} Execution flow: `query_extractor` -> `query_checker` -> route function * * * ## Using Dependencies in Decorators Sometimes you only need the side effects of a dependency (such as permission verification) without its return value. You can declare it in the `dependencies` parameter of the decorator: ## Example from fastapi import Depends, FastAPI, Header, HTTPException app = FastAPI() # Dependency: validate API Key async def verify_api_key(x_api_key: str= Header()): if x_api_key !="secret-key": raise HTTPException(status_code=400, detail="X-API-Key invalid") # Use dependency in decorator, no return value needed @app.get("/items/", dependencies=[Depends(verify_api_key)]) async def read_items(): return[{"item": "Foo"}] # Apply dependency to an entire route group @app.get("/users/", dependencies=[Depends(verify_api_key)]) async def read_users(): return[{"user": "Bar"}] * * * ## Global Dependencies You can declare global dependencies on the `FastAPI` instance to apply them to all routes: ## Example from fastapi import Depends, FastAPI, Header, HTTPException async def verify_token(x_token: str= Header()): if x_token !="fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") # Global dependency: all routes require token verification app = FastAPI(dependencies=[Depends(verify_token)]) @app.get("/items/") async def read_items(): return[{"item": "Foo"}] @app.get("/users/") async def read_users(): return[{"user": "Bar"}] * * * ## Dependencies Using yield When a dependency needs to perform cleanup operations (such as closing database connections), use `yield`: ## Example from typing import Annotated from fastapi import Depends, FastAPI app = FastAPI() # Dependency using yield: create connection before request, close after request def get_db(): db ="database_connection"# Simulate creating database connection try: yield db # Provide database connection during request processing finally: print("Closing database connection")# Clean up resources after request @app.get("/items/") async def read_items(db: str= Depends(get_db)): return{"db": db} Execution flow: 1. When the request arrives, execute the code before `yield`, create database connection 2. `yield` passes the connection to the route function 3. After the route function completes execution, execute the cleanup code in the `finally` block > `yield` dependencies are ideal for managing resources that need cleanup, such as database connections, file handles, etc. The cleanup code will execute regardless of whether the route function throws an exception. * * * ## Summary * Dependency injection extracts common logic into reusable functions or classes * Use `Depends()` in route function parameters to declare dependencies * Dependencies can be nested, forming dependency chains * The `dependencies` parameter in decorators is used for dependencies that don't require return values * Dependencies using `yield` support resource cleanup * Global dependencies apply to all routes
← Csharp Variable ScopeFastapi Request Response β†’