mirror of https://github.com/tiangolo/fastapi.git
Merge branch 'master' into master
This commit is contained in:
commit
a0541ab1bb
|
|
@ -70,12 +70,22 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
|
|||
|
||||
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
|
||||
|
||||
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
|
||||
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
|
||||
|
||||
///
|
||||
|
||||
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
|
||||
|
||||
### Abhängigkeiten mit `yield` und `scope` { #dependencies-with-yield-and-scope }
|
||||
|
||||
In Version 0.121.0 hat FastAPI Unterstützung für `Depends(scope="function")` für Abhängigkeiten mit `yield` hinzugefügt.
|
||||
|
||||
Mit `Depends(scope="function")` wird der Exit-Code nach `yield` direkt nach dem Ende der *Pfadoperation-Funktion* ausgeführt, bevor die Response an den Client gesendet wird.
|
||||
|
||||
Und bei Verwendung von `Depends(scope="request")` (dem Default) wird der Exit-Code nach `yield` ausgeführt, nachdem die Response gesendet wurde.
|
||||
|
||||
Mehr dazu finden Sie in der Dokumentation zu [Abhängigkeiten mit `yield` – Frühes Beenden und `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
|
||||
|
||||
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
|
||||
|
||||
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.
|
||||
|
|
|
|||
|
|
@ -184,6 +184,51 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
|
|||
|
||||
///
|
||||
|
||||
## Frühes Beenden und `scope` { #early-exit-and-scope }
|
||||
|
||||
Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
|
||||
|
||||
Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
|
||||
`Depends()` erhält einen `scope`-Parameter, der sein kann:
|
||||
|
||||
* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
|
||||
* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
|
||||
|
||||
Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
|
||||
|
||||
### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
|
||||
|
||||
Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
|
||||
|
||||
Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
|
||||
|
||||
Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant client as Client
|
||||
participant dep_req as Abhängigkeit scope="request"
|
||||
participant dep_func as Abhängigkeit scope="function"
|
||||
participant operation as Pfadoperation
|
||||
|
||||
client ->> dep_req: Startet den Request
|
||||
Note over dep_req: Führt den Code bis zum yield aus
|
||||
dep_req ->> dep_func: Reicht Abhängigkeit weiter
|
||||
Note over dep_func: Führt den Code bis zum yield aus
|
||||
dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
|
||||
operation ->> dep_func: Kehrt aus Pfadoperation zurück
|
||||
Note over dep_func: Führt Code nach yield aus
|
||||
Note over dep_func: ✅ Abhängigkeit geschlossen
|
||||
dep_func ->> client: Sendet Response an Client
|
||||
Note over client: Response gesendet
|
||||
Note over dep_req: Führt Code nach yield aus
|
||||
Note over dep_req: ✅ Abhängigkeit geschlossen
|
||||
```
|
||||
|
||||
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||
|
||||
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@ hide:
|
|||
|
||||
## Latest Changes
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Sync German docs. PR [#14317](https://github.com/fastapi/fastapi/pull/14317) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
|
||||
## 0.121.1
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Fix `Depends(func, scope='function')` for top level (parameterless) dependencies. PR [#14301](https://github.com/fastapi/fastapi/pull/14301) by [@luzzodev](https://github.com/luzzodev).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.121.0"
|
||||
__version__ = "0.121.1"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,10 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De
|
|||
if isinstance(depends, params.Security) and depends.scopes:
|
||||
use_security_scopes.extend(depends.scopes)
|
||||
return get_dependant(
|
||||
path=path, call=depends.dependency, security_scopes=use_security_scopes
|
||||
path=path,
|
||||
call=depends.dependency,
|
||||
scope=depends.scope,
|
||||
security_scopes=use_security_scopes,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import json
|
|||
from typing import Any, Tuple
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi import APIRouter, Depends, FastAPI, HTTPException
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -20,6 +20,11 @@ def dep_session() -> Any:
|
|||
s.open = False
|
||||
|
||||
|
||||
def raise_after_yield() -> Any:
|
||||
yield
|
||||
raise HTTPException(status_code=503, detail="Exception after yield")
|
||||
|
||||
|
||||
SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")]
|
||||
SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")]
|
||||
SessionDefaultDep = Annotated[Session, Depends(dep_session)]
|
||||
|
|
@ -64,6 +69,12 @@ RegularSessionsDep = Annotated[
|
|||
]
|
||||
|
||||
app = FastAPI()
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/")
|
||||
def get_index():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@app.get("/function-scope")
|
||||
|
|
@ -124,6 +135,18 @@ def get_regular_function_scope(sessions: RegularSessionsDep) -> Any:
|
|||
return StreamingResponse(iter_data())
|
||||
|
||||
|
||||
app.include_router(
|
||||
prefix="/router-scope-function",
|
||||
router=router,
|
||||
dependencies=[Depends(raise_after_yield, scope="function")],
|
||||
)
|
||||
|
||||
app.include_router(
|
||||
prefix="/router-scope-request",
|
||||
router=router,
|
||||
dependencies=[Depends(raise_after_yield, scope="request")],
|
||||
)
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
|
|
@ -182,3 +205,42 @@ def test_regular_function_scope() -> None:
|
|||
data = response.json()
|
||||
assert data["named_session_open"] is True
|
||||
assert data["session_open"] is False
|
||||
|
||||
|
||||
def test_router_level_dep_scope_function() -> None:
|
||||
response = client.get("/router-scope-function/")
|
||||
assert response.status_code == 503
|
||||
assert response.json() == {"detail": "Exception after yield"}
|
||||
|
||||
|
||||
def test_router_level_dep_scope_request() -> None:
|
||||
with TestClient(app, raise_server_exceptions=False) as client:
|
||||
response = client.get("/router-scope-request/")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
||||
|
||||
def test_app_level_dep_scope_function() -> None:
|
||||
app = FastAPI(dependencies=[Depends(raise_after_yield, scope="function")])
|
||||
|
||||
@app.get("/app-scope-function")
|
||||
def get_app_scope_function():
|
||||
return {"status": "ok"}
|
||||
|
||||
with TestClient(app) as client:
|
||||
response = client.get("/app-scope-function")
|
||||
assert response.status_code == 503
|
||||
assert response.json() == {"detail": "Exception after yield"}
|
||||
|
||||
|
||||
def test_app_level_dep_scope_request() -> None:
|
||||
app = FastAPI(dependencies=[Depends(raise_after_yield, scope="request")])
|
||||
|
||||
@app.get("/app-scope-request")
|
||||
def get_app_scope_request():
|
||||
return {"status": "ok"}
|
||||
|
||||
with TestClient(app, raise_server_exceptions=False) as client:
|
||||
response = client.get("/app-scope-request")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
|
|
|||
Loading…
Reference in New Issue