- Spec files
pypi-fastapi
Describes: pkg:pypi/fastapi@0.116.x
- Description
- FastAPI framework, high performance, easy to learn, fast to code, ready for production
- Author
- tessl
- Last updated
dependency-injection.md docs/
1# Dependency Injection23FastAPI provides a powerful dependency injection system that allows sharing code, database connections, authentication, and other common functionality across endpoints. Dependencies are cached by default and can be overridden for testing.45## Capabilities67### Depends Function89Core dependency injection function that declares dependencies with optional caching control.1011```python { .api }12def Depends(dependency: Callable = None, *, use_cache: bool = True) -> Any:13"""14Declare a dependency for dependency injection.1516Parameters:17- dependency: Callable that provides the dependency value18- use_cache: Whether to cache the dependency result within a request1920Returns:21Dependency declaration for use in function signatures2223The dependency callable can be:24- A function that returns a value25- A class constructor26- Another dependency that uses Depends()27- A callable with its own dependencies28"""29```3031### Security Dependencies3233Special dependency function for security-related dependencies with scope support for authorization.3435```python { .api }36def Security(37dependency: Callable = None,38*,39scopes: List[str] = None,40use_cache: bool = True,41) -> Any:42"""43Declare a security dependency with OAuth2 scopes support.4445Parameters:46- dependency: Security scheme callable (e.g., OAuth2PasswordBearer)47- scopes: List of required OAuth2 scopes for authorization48- use_cache: Whether to cache the dependency result within a request4950Returns:51Security dependency declaration for use in function signatures5253Used for endpoints that require specific permissions or scopes.54"""55```5657## Usage Examples5859### Basic Dependencies6061```python62from fastapi import FastAPI, Depends6364app = FastAPI()6566# Simple dependency function67def get_db():68db = {"connection": "postgresql://..."}69try:70yield db71finally:72# Close connection73pass7475def get_current_user():76return {"user_id": 1, "username": "john"}7778@app.get("/items/")79def read_items(80db=Depends(get_db),81current_user=Depends(get_current_user)82):83return {"db": db, "user": current_user}84```8586### Class-based Dependencies8788```python89from fastapi import FastAPI, Depends9091app = FastAPI()9293class DatabaseService:94def __init__(self):95self.connection = "postgresql://..."9697def get_connection(self):98return self.connection99100class UserService:101def __init__(self, db: DatabaseService = Depends(DatabaseService)):102self.db = db103104def get_current_user(self):105return {"user_id": 1, "username": "john"}106107@app.get("/users/me")108def get_user_profile(user_service: UserService = Depends(UserService)):109return user_service.get_current_user()110```111112### Dependency with Parameters113114```python115from fastapi import FastAPI, Depends, Query116117app = FastAPI()118119def common_parameters(120skip: int = Query(0, ge=0),121limit: int = Query(10, ge=1, le=100)122):123return {"skip": skip, "limit": limit}124125@app.get("/items/")126def read_items(commons: dict = Depends(common_parameters)):127return {"params": commons}128129@app.get("/users/")130def read_users(commons: dict = Depends(common_parameters)):131return {"params": commons}132```133134### Nested Dependencies135136```python137from fastapi import FastAPI, Depends, HTTPException138139app = FastAPI()140141def get_db():142return {"connection": "active"}143144def get_user_service(db=Depends(get_db)):145return {"db": db, "service": "user_service"}146147def get_current_user(user_service=Depends(get_user_service)):148# Authentication logic using user_service149return {"user_id": 1, "username": "john"}150151def get_admin_user(current_user=Depends(get_current_user)):152if not current_user.get("is_admin"):153raise HTTPException(status_code=403, detail="Admin required")154return current_user155156@app.get("/admin/users")157def list_users(admin_user=Depends(get_admin_user)):158return {"message": "Admin access granted", "admin": admin_user}159```160161### Dependency Caching162163```python164from fastapi import FastAPI, Depends165import time166167app = FastAPI()168169# Expensive operation that should be cached170def get_expensive_data():171print("Computing expensive data...")172time.sleep(1) # Simulate expensive operation173return {"data": "expensive_result", "timestamp": time.time()}174175# Cached dependency (default behavior)176def cached_dependency():177return get_expensive_data()178179# Non-cached dependency180def non_cached_dependency():181return get_expensive_data()182183@app.get("/cached")184def endpoint_with_cached_deps(185data1=Depends(cached_dependency),186data2=Depends(cached_dependency) # Same result, computed only once187):188return {"data1": data1, "data2": data2}189190@app.get("/non-cached")191def endpoint_with_non_cached_deps(192data1=Depends(non_cached_dependency, use_cache=False),193data2=Depends(non_cached_dependency, use_cache=False) # Computed twice194):195return {"data1": data1, "data2": data2}196```197198### Global Dependencies199200```python201from fastapi import FastAPI, Depends, HTTPException202203# Global authentication dependency204def verify_api_key(api_key: str = Header(...)):205if api_key != "secret-api-key":206raise HTTPException(status_code=401, detail="Invalid API key")207return api_key208209# Apply dependency to entire application210app = FastAPI(dependencies=[Depends(verify_api_key)])211212@app.get("/protected-endpoint")213def protected_endpoint():214return {"message": "This endpoint requires API key"}215216@app.get("/another-protected-endpoint")217def another_protected_endpoint():218return {"message": "This endpoint also requires API key"}219```220221### Router-level Dependencies222223```python224from fastapi import FastAPI, APIRouter, Depends, HTTPException225226app = FastAPI()227228def admin_required():229# Authentication logic230return {"role": "admin"}231232# Router with shared dependencies233admin_router = APIRouter(234prefix="/admin",235dependencies=[Depends(admin_required)]236)237238@admin_router.get("/users")239def admin_list_users():240return {"users": ["admin", "user1", "user2"]}241242@admin_router.delete("/users/{user_id}")243def admin_delete_user(user_id: int):244return {"message": f"User {user_id} deleted"}245246app.include_router(admin_router)247```248249### Security Dependencies with Scopes250251```python252from fastapi import FastAPI, Depends, HTTPException, Security253from fastapi.security import OAuth2PasswordBearer254from typing import List255256app = FastAPI()257258oauth2_scheme = OAuth2PasswordBearer(259tokenUrl="token",260scopes={261"read": "Read access",262"write": "Write access",263"admin": "Admin access"264}265)266267def get_current_user(token: str = Depends(oauth2_scheme)):268# Decode token and return user269return {"username": "john", "scopes": ["read", "write"]}270271def check_scopes(required_scopes: List[str]):272def scopes_checker(273current_user=Security(oauth2_scheme, scopes=required_scopes)274):275user_scopes = current_user.get("scopes", [])276for scope in required_scopes:277if scope not in user_scopes:278raise HTTPException(279status_code=403,280detail=f"Not enough permissions. Required: {required_scopes}"281)282return current_user283return scopes_checker284285@app.get("/read-data")286def read_data(287current_user=Security(oauth2_scheme, scopes=["read"])288):289return {"data": "sensitive data", "user": current_user}290291@app.post("/write-data")292def write_data(293current_user=Security(oauth2_scheme, scopes=["write"])294):295return {"message": "Data written", "user": current_user}296297@app.delete("/admin-action")298def admin_action(299current_user=Security(oauth2_scheme, scopes=["admin"])300):301return {"message": "Admin action performed", "user": current_user}302```303304### Dependency Override for Testing305306```python307from fastapi import FastAPI, Depends308from fastapi.testclient import TestClient309310app = FastAPI()311312def get_db():313return {"connection": "production_db"}314315def get_current_user():316return {"user_id": 1, "username": "john"}317318@app.get("/items/")319def read_items(320db=Depends(get_db),321current_user=Depends(get_current_user)322):323return {"db": db, "user": current_user}324325# Test with dependency overrides326def test_read_items():327def override_get_db():328return {"connection": "test_db"}329330def override_get_current_user():331return {"user_id": 999, "username": "test_user"}332333app.dependency_overrides[get_db] = override_get_db334app.dependency_overrides[get_current_user] = override_get_current_user335336client = TestClient(app)337response = client.get("/items/")338339# Clean up overrides340app.dependency_overrides = {}341342assert response.status_code == 200343data = response.json()344assert data["db"]["connection"] == "test_db"345assert data["user"]["username"] == "test_user"346```347348### Dependency with Cleanup349350```python351from fastapi import FastAPI, Depends352import asyncio353354app = FastAPI()355356class DatabaseConnection:357def __init__(self):358self.connection = None359360async def connect(self):361print("Connecting to database...")362self.connection = "active_connection"363return self364365async def disconnect(self):366print("Disconnecting from database...")367self.connection = None368369async def get_database():370db = DatabaseConnection()371await db.connect()372try:373yield db374finally:375await db.disconnect()376377@app.get("/items/")378async def read_items(db: DatabaseConnection = Depends(get_database)):379return {"connection_status": db.connection}380```