Skip to content

How-to: FastAPI Depends-Muster

So verwenden Sie FastAPIs Depends() und die Konvention, sich auf den Annotated-Stil zu standardisieren.


1. Zwei Depends-Stile

FastAPI bietet zwei Möglichkeiten, Depends() zu schreiben.

python
# Stil A: = Depends(...) (Standardwert-Stil)
def handler(
    use_case: FetchUserUseCase = Depends(get_fetch_user_use_case),
) -> JSONResponse: ...

# Stil B: Annotated[T, Depends(...)] (Annotated-Stil)
def handler(
    use_case: Annotated[FetchUserUseCase, Depends(get_fetch_user_use_case)],
) -> JSONResponse: ...

Empfohlen: Standardisieren Sie auf den Annotated-Stil (Stil B).


2. SyntaxError beim Mischen der Stile

Das Mischen von = Depends(...) und Annotated[T, Depends()] in derselben Funktion löst einen SyntaxError aus.

python
# ❌ SyntaxError: parameter without a default follows parameter with a default
def list_articles(
    filter_: ArticleFilter = Depends(get_filter),   # hat einen Standardwert
    pagination: Annotated[PaginationQueryParser, Depends()],  # kein Standardwert
) -> JSONResponse: ...

# ✅ auf den Annotated-Stil standardisieren
def list_articles(
    filter_: Annotated[ArticleFilter, Depends(get_filter)],
    pagination: Annotated[PaginationQueryParser, Depends()],
) -> JSONResponse: ...

Als Python-Regel kann ein Parameter ohne Standardwert nicht auf einen mit Standardwert folgen. Annotated[T, Depends()] hat keinen Standardwert, daher kann er nicht nach = Depends(...) kommen.


3. Die korrekte Verwendung von PaginationQueryParser

Verwenden Sie PaginationQueryParser mit Annotated[T, Depends()]. Es gibt kein as_depends().

python
from typing import Annotated
from fastapi import Depends
from nene2.http import PaginationQueryParser

# ✅ korrekt
def list_items(
    pagination: Annotated[PaginationQueryParser, Depends()],
) -> JSONResponse:
    result = use_case.execute(pagination.limit, pagination.offset)
    ...

# ❌ as_depends() existiert nicht
def list_items(
    pagination: PaginationQueryParser = Depends(PaginationQueryParser.as_depends()),
) -> JSONResponse: ...

4. Benutzerdefinierter Filter + Paginierung

Wenn mehrere Depends()-Parameter kombiniert werden, standardisieren Sie alle auf den Annotated-Stil.

python
from dataclasses import dataclass
from enum import StrEnum
from typing import Annotated

from fastapi import Depends, FastAPI, Query
from fastapi.responses import JSONResponse

from nene2.http import PaginationQueryParser


class Status(StrEnum):
    ACTIVE = "active"
    INACTIVE = "inactive"


@dataclass(frozen=True, slots=True)
class ItemFilter:
    status: Status | None
    tag: str | None


def get_item_filter(
    status: Annotated[Status | None, Query()] = None,
    tag: Annotated[str | None, Query(max_length=50)] = None,
) -> ItemFilter:
    return ItemFilter(status=status, tag=tag)


@app.get("/items")
def list_items(
    filter_: Annotated[ItemFilter, Depends(get_item_filter)],
    pagination: Annotated[PaginationQueryParser, Depends()],
) -> JSONResponse:
    # Filter: filter_.status, filter_.tag
    # Paginierung: pagination.limit, pagination.offset
    ...

5. Einen Cache über Depends injizieren

Ein Beispiel für das Injizieren eines app.state-Caches im Annotated-Stil.

python
from fastapi import Request
from nene2.cache import TtlCache

def get_cache(request: Request) -> TtlCache[dict[str, object]]:
    return request.app.state.cache  # type: ignore[attr-defined]

@app.get("/items/{item_id}")
def get_item(
    item_id: int,
    cache: Annotated[TtlCache[dict[str, object]], Depends(get_cache)],
) -> JSONResponse:
    ...

Veröffentlicht unter der MIT-Lizenz.