File size: 4,267 Bytes
a152b95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# Dependency Injection in FastAPI

FastAPI includes a built-in dependency injection system that allows you to share logic, enforce authentication, manage database connections, and more. Dependencies are declared using `Depends()` and are resolved automatically for each request.

## Basic Dependency

A dependency is any callable (function or class) that FastAPI calls before the route handler:

```python
from fastapi import FastAPI, Depends, Query

app = FastAPI()

async def common_parameters(
    skip: int = Query(default=0, ge=0),
    limit: int = Query(default=100, ge=1, le=1000),
):
    return {"skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return {"params": commons}

@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return {"params": commons}
```

Both `/items/` and `/users/` share the same pagination logic. The `common_parameters` function is called once per request, and its return value is injected into the `commons` parameter.

## Class-Based Dependencies

Classes work as dependencies because calling a class creates an instance (i.e., `MyClass()` is callable):

```python
class PaginationParams:
    def __init__(
        self,
        skip: int = Query(default=0, ge=0),
        limit: int = Query(default=100, ge=1, le=1000),
    ):
        self.skip = skip
        self.limit = limit

@app.get("/items/")
async def read_items(pagination: PaginationParams = Depends(PaginationParams)):
    return {"skip": pagination.skip, "limit": pagination.limit}
```

FastAPI provides a shorthand: `Depends(PaginationParams)` can also be written as `Depends()` when the type annotation already specifies the class: `pagination: PaginationParams = Depends()`.

## Sub-Dependencies

Dependencies can depend on other dependencies, forming a chain that FastAPI resolves automatically:

```python
def query_extractor(q: str | None = None):
    return q

def query_or_default(q: str = Depends(query_extractor)):
    if not q:
        return "default_query"
    return q

@app.get("/items/")
async def read_items(query: str = Depends(query_or_default)):
    return {"query": query}
```

FastAPI resolves the dependency tree from the leaves up. In this case, `query_extractor` runs first, then `query_or_default` receives its result. The maximum depth of the dependency chain is not explicitly limited, but in practice chains deeper than 10 levels indicate a design issue.

## Dependencies with Yield (Resource Management)

Use `yield` in a dependency to run setup code before and cleanup code after the route handler executes. This is ideal for managing database sessions, file handles, or locks:

```python
from sqlalchemy.orm import Session

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/items/")
async def read_items(db: Session = Depends(get_db)):
    items = db.query(Item).all()
    return items
```

The code before `yield` runs before the handler, the yielded value is injected as the dependency, and the code after `yield` runs after the response is sent. The `finally` block ensures cleanup happens even if an exception occurs. FastAPI supports up to 32 yield dependencies per request by default.

## Global Dependencies

Apply dependencies to every route in the application by passing them to the `FastAPI` constructor:

```python
from fastapi import FastAPI, Depends, Header, HTTPException

async def verify_api_key(x_api_key: str = Header()):
    if x_api_key != "secret-key-123":
        raise HTTPException(status_code=403, detail="Invalid API key")

app = FastAPI(dependencies=[Depends(verify_api_key)])

@app.get("/items/")
async def read_items():
    return [{"item": "Widget"}]
```

Every route in this application requires a valid `X-Api-Key` header. You can also scope dependencies to a specific router using `APIRouter(dependencies=[...])`.

## Caching Behavior

By default, if the same dependency is used multiple times within a single request (e.g., both a route and a sub-dependency use `Depends(get_db)`), FastAPI caches the result and calls the dependency only once. To disable caching and force a fresh call each time, use `Depends(get_db, use_cache=False)`.