or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

api-routing.mdbackground-tasks.mdcore-application.mddependency-injection.mdexception-handling.mdfile-handling.mdindex.mdparameter-declaration.mdrequest-response.mdwebsocket-support.md

dependency-injection.mddocs/

0

# Dependency Injection

1

2

FastAPI's dependency injection system provides automatic resolution of dependencies with hierarchical composition, caching, and security integration. Dependencies can be functions, classes, or any callable that FastAPI can inspect and resolve automatically.

3

4

## Capabilities

5

6

### Depends Function

7

8

Core function for declaring dependencies with automatic resolution and caching.

9

10

```python { .api }

11

def Depends(dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True) -> Any:

12

"""

13

Declare a dependency for automatic injection and resolution.

14

15

Parameters:

16

- dependency: Callable to be invoked as a dependency (function, class, or callable)

17

If None, uses the type annotation of the parameter as the dependency

18

- use_cache: Whether to cache the result of this dependency per request

19

Can be set to False to call the dependency function multiple times per request

20

21

Returns:

22

Dependency marker that FastAPI uses for automatic resolution

23

24

Behaviors:

25

- Dependencies are resolved recursively (dependencies can have their own dependencies)

26

- Results are cached per request by default to avoid multiple calls

27

- Dependencies are resolved before calling the endpoint function

28

- Failed dependencies prevent endpoint execution and return appropriate HTTP errors

29

- Sub-dependencies are resolved in dependency order

30

"""

31

```

32

33

### Security Function

34

35

Function for declaring security dependencies with OAuth2 scope support and automatic OpenAPI security schema generation.

36

37

```python { .api }

38

def Security(

39

dependency: Optional[Callable[..., Any]] = None,

40

*,

41

scopes: Optional[Sequence[str]] = None,

42

use_cache: bool = True

43

) -> Any:

44

"""

45

Declare a security dependency with optional OAuth2 scopes.

46

47

Parameters:

48

- dependency: Security callable (typically an OAuth2 or API key scheme)

49

- scopes: List of OAuth2 scopes required for this endpoint

50

- use_cache: Whether to cache the result of this dependency per request

51

52

Returns:

53

Security dependency marker for automatic resolution

54

55

Behaviors:

56

- Integrates with OpenAPI security schemas

57

- Supports OAuth2 scopes for fine-grained permission control

58

- Automatically generates OpenAPI security requirements

59

- Can be combined with regular Depends() for complex security patterns

60

"""

61

```

62

63

## Dependency Patterns

64

65

### Function Dependencies

66

67

Simple functions that return values or perform setup operations.

68

69

```python { .api }

70

def get_database_connection():

71

"""

72

Example function dependency that provides database connection.

73

74

Returns:

75

Database connection object

76

"""

77

78

def get_current_user(token: str = Depends(get_auth_token)):

79

"""

80

Example function dependency with sub-dependency.

81

82

Parameters:

83

- token: Authentication token from sub-dependency

84

85

Returns:

86

Current user object

87

"""

88

```

89

90

### Class Dependencies

91

92

Classes used as dependencies, typically for configuration or service objects.

93

94

```python { .api }

95

class DatabaseManager:

96

def __init__(self, connection_string: str = Depends(get_connection_string)):

97

"""

98

Example class dependency with constructor injection.

99

100

Parameters:

101

- connection_string: Database connection string from dependency

102

"""

103

104

def get_connection(self):

105

"""Get database connection."""

106

```

107

108

### Async Dependencies

109

110

Dependencies that perform asynchronous operations.

111

112

```python { .api }

113

async def get_async_resource():

114

"""

115

Example async dependency for I/O operations.

116

117

Returns:

118

Async resource or data

119

"""

120

121

async def validate_async_token(token: str = Depends(get_token)):

122

"""

123

Example async dependency with token validation.

124

125

Parameters:

126

- token: Token to validate

127

128

Returns:

129

Validated user information

130

131

Raises:

132

HTTPException: If token is invalid

133

"""

134

```

135

136

### Generator Dependencies

137

138

Dependencies that provide resources with automatic cleanup using context managers.

139

140

```python { .api }

141

def get_database_session():

142

"""

143

Example generator dependency with automatic cleanup.

144

145

Yields:

146

Database session object

147

148

Note: Cleanup code runs after endpoint execution

149

"""

150

151

async def get_async_session():

152

"""

153

Example async generator dependency with automatic cleanup.

154

155

Yields:

156

Async database session object

157

"""

158

```

159

160

## Usage Examples

161

162

### Basic Dependencies

163

164

```python

165

from fastapi import FastAPI, Depends, HTTPException

166

167

app = FastAPI()

168

169

# Simple dependency function

170

def get_database():

171

# In real app, this would return actual database connection

172

return {"type": "database", "status": "connected"}

173

174

def get_current_user(db = Depends(get_database)):

175

# Simulate user lookup

176

user = db.get("current_user") # This would be actual DB query

177

if not user:

178

raise HTTPException(status_code=401, detail="User not found")

179

return {"user_id": 1, "username": "john", "is_active": True}

180

181

@app.get("/users/me")

182

async def get_user_profile(current_user: dict = Depends(get_current_user)):

183

return current_user

184

185

@app.get("/items/")

186

async def get_items(

187

db = Depends(get_database),

188

current_user: dict = Depends(get_current_user)

189

):

190

# Both dependencies are resolved automatically

191

return {

192

"items": ["item1", "item2"],

193

"user": current_user["username"],

194

"db_status": db["status"]

195

}

196

```

197

198

### Class-Based Dependencies

199

200

```python

201

from fastapi import FastAPI, Depends

202

203

app = FastAPI()

204

205

class Settings:

206

def __init__(self):

207

self.api_key = "secret-key"

208

self.debug = True

209

self.max_connections = 100

210

211

class DatabaseManager:

212

def __init__(self, settings: Settings = Depends(Settings)):

213

self.settings = settings

214

self.connection_pool = f"pool-{settings.max_connections}"

215

216

def get_connection(self):

217

return f"connection-{self.settings.api_key}"

218

219

@app.get("/config")

220

async def get_config(

221

settings: Settings = Depends(Settings),

222

db: DatabaseManager = Depends(DatabaseManager)

223

):

224

return {

225

"debug": settings.debug,

226

"connection": db.get_connection()

227

}

228

```

229

230

### Security Dependencies

231

232

```python

233

from fastapi import FastAPI, Depends, HTTPException, Security

234

from fastapi.security import HTTPBearer, OAuth2PasswordBearer

235

236

app = FastAPI()

237

238

# HTTP Bearer token security

239

security = HTTPBearer()

240

241

def verify_token(token: str = Depends(security)):

242

if token.credentials != "valid-token":

243

raise HTTPException(status_code=401, detail="Invalid token")

244

return token.credentials

245

246

# OAuth2 with scopes

247

oauth2_scheme = OAuth2PasswordBearer(

248

tokenUrl="token",

249

scopes={"read": "Read access", "write": "Write access"}

250

)

251

252

def get_current_user(token: str = Depends(oauth2_scheme)):

253

# Verify token and return user

254

return {"user_id": 1, "username": "john", "scopes": ["read", "write"]}

255

256

def require_scopes(required_scopes: list):

257

def check_scopes(current_user: dict = Security(get_current_user, scopes=required_scopes)):

258

user_scopes = current_user.get("scopes", [])

259

for scope in required_scopes:

260

if scope not in user_scopes:

261

raise HTTPException(status_code=403, detail="Insufficient permissions")

262

return current_user

263

return check_scopes

264

265

@app.get("/public")

266

async def public_endpoint():

267

return {"message": "This is public"}

268

269

@app.get("/protected")

270

async def protected_endpoint(user: dict = Depends(get_current_user)):

271

return {"message": f"Hello {user['username']}"}

272

273

@app.post("/admin/users")

274

async def create_user(user: dict = Security(get_current_user, scopes=["write"])):

275

return {"message": "User created", "by": user["username"]}

276

```

277

278

### Async Dependencies

279

280

```python

281

import asyncio

282

from fastapi import FastAPI, Depends, HTTPException

283

284

app = FastAPI()

285

286

async def get_async_database():

287

# Simulate async database connection

288

await asyncio.sleep(0.1)

289

return {"type": "async_db", "status": "connected"}

290

291

async def get_external_data():

292

# Simulate external API call

293

await asyncio.sleep(0.2)

294

return {"data": "external_value", "timestamp": "2023-01-01"}

295

296

async def validate_user_async(

297

db = Depends(get_async_database),

298

external_data = Depends(get_external_data)

299

):

300

# Perform async validation

301

if external_data["data"] != "external_value":

302

raise HTTPException(status_code=400, detail="Validation failed")

303

304

return {

305

"user_id": 1,

306

"username": "async_user",

307

"validated_at": external_data["timestamp"]

308

}

309

310

@app.get("/async-endpoint")

311

async def async_endpoint(

312

user = Depends(validate_user_async),

313

db = Depends(get_async_database)

314

):

315

return {

316

"user": user,

317

"db_status": db["status"]

318

}

319

```

320

321

### Generator Dependencies with Cleanup

322

323

```python

324

from fastapi import FastAPI, Depends

325

import contextlib

326

327

app = FastAPI()

328

329

def get_database_session():

330

"""Generator dependency with automatic cleanup."""

331

print("Creating database session")

332

session = {"id": "session_123", "active": True}

333

try:

334

yield session

335

finally:

336

print("Closing database session")

337

session["active"] = False

338

339

async def get_async_resource():

340

"""Async generator dependency with cleanup."""

341

print("Acquiring async resource")

342

resource = {"handle": "resource_456", "open": True}

343

try:

344

yield resource

345

finally:

346

print("Releasing async resource")

347

resource["open"] = False

348

349

@app.get("/with-cleanup")

350

async def endpoint_with_cleanup(

351

db_session = Depends(get_database_session),

352

async_resource = Depends(get_async_resource)

353

):

354

# Resources are automatically cleaned up after response

355

return {

356

"session_id": db_session["id"],

357

"resource_handle": async_resource["handle"]

358

}

359

```

360

361

### Dependency Overriding

362

363

```python

364

from fastapi import FastAPI, Depends

365

from fastapi.testclient import TestClient

366

367

app = FastAPI()

368

369

def get_database():

370

return {"type": "production", "host": "prod.db"}

371

372

def get_current_user(db = Depends(get_database)):

373

return {"user_id": 1, "username": "prod_user"}

374

375

@app.get("/data")

376

async def get_data(user = Depends(get_current_user)):

377

return {"data": "sensitive_data", "user": user["username"]}

378

379

# Test with dependency overrides

380

def get_test_database():

381

return {"type": "test", "host": "test.db"}

382

383

def get_test_user(db = Depends(get_test_database)):

384

return {"user_id": 999, "username": "test_user"}

385

386

# In tests:

387

# app.dependency_overrides[get_database] = get_test_database

388

# app.dependency_overrides[get_current_user] = get_test_user

389

```

390

391

### Sub-Dependencies and Caching

392

393

```python

394

from fastapi import FastAPI, Depends

395

import time

396

397

app = FastAPI()

398

399

def expensive_computation():

400

"""Expensive operation that should be cached."""

401

print("Performing expensive computation...")

402

time.sleep(1) # Simulate expensive operation

403

return {"result": "computed_value", "timestamp": time.time()}

404

405

def get_user_data(computation = Depends(expensive_computation)):

406

return {

407

"user_id": 1,

408

"computed_result": computation["result"]

409

}

410

411

def get_admin_data(computation = Depends(expensive_computation)):

412

return {

413

"admin_id": 1,

414

"computed_result": computation["result"]

415

}

416

417

@app.get("/user-and-admin")

418

async def get_both_data(

419

user_data = Depends(get_user_data),

420

admin_data = Depends(get_admin_data)

421

):

422

# expensive_computation() is called only once due to caching

423

return {

424

"user": user_data,

425

"admin": admin_data

426

}

427

428

# Disable caching for specific dependency

429

def no_cache_computation():

430

print("Computation without caching...")

431

return {"result": "fresh_value", "timestamp": time.time()}

432

433

def get_fresh_data(computation = Depends(no_cache_computation, use_cache=False)):

434

return {"fresh_result": computation["result"]}

435

436

@app.get("/fresh-data")

437

async def get_multiple_fresh(

438

data1 = Depends(get_fresh_data),

439

data2 = Depends(get_fresh_data)

440

):

441

# no_cache_computation() is called twice due to use_cache=False

442

return {"data1": data1, "data2": data2}

443

```