🔧 Update docs setup with latest configs and plugins (#11953)

This commit is contained in:
Sebastián Ramírez authored and GitHub committed 2024-08-05 23:48:30 -05:00
1 parent af1a07052a
commit 0cd844d387
643 files changed
+37193 -21694

No files matched your search

+40 -24
View File
@@ -57,41 +57,57 @@ Die Verwendung von `BackgroundTasks` funktioniert auch mit dem <abbr title="Einb
**FastAPI** weiß, was jeweils zu tun ist und wie dasselbe Objekt wiederverwendet werden kann, sodass alle Hintergrundtasks zusammengeführt und anschließend im Hintergrund ausgeführt werden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
```
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
```
```Python hl_lines="14 16 23 26"
{!> ../../../docs_src/background_tasks/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="14 16 23 26"
{!> ../../../docs_src/background_tasks/tutorial002_an.py!}
```
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002.py!}
```
////
In obigem Beispiel werden die Nachrichten, *nachdem* die Response gesendet wurde, in die Datei `log.txt` geschrieben.
+116 -65
View File
@@ -4,8 +4,11 @@ Wenn Sie eine Anwendung oder eine Web-API erstellen, ist es selten der Fall, das
**FastAPI** bietet ein praktisches Werkzeug zur Strukturierung Ihrer Anwendung bei gleichzeitiger Wahrung der Flexibilität.
!!! info
Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints.
/// info
Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints.
///
## Eine Beispiel-Dateistruktur
@@ -26,16 +29,19 @@ Nehmen wir an, Sie haben eine Dateistruktur wie diese:
│   └── admin.py
```
!!! tip "Tipp"
Es gibt mehrere `__init__.py`-Dateien: eine in jedem Verzeichnis oder Unterverzeichnis.
/// tip | "Tipp"
Das ermöglicht den Import von Code aus einer Datei in eine andere.
Es gibt mehrere `__init__.py`-Dateien: eine in jedem Verzeichnis oder Unterverzeichnis.
In `app/main.py` könnten Sie beispielsweise eine Zeile wie diese haben:
Das ermöglicht den Import von Code aus einer Datei in eine andere.
```
from app.routers import items
```
In `app/main.py` könnten Sie beispielsweise eine Zeile wie diese haben:
```
from app.routers import items
```
///
* Das Verzeichnis `app` enthält alles. Und es hat eine leere Datei `app/__init__.py`, es handelt sich also um ein „Python-Package“ (eine Sammlung von „Python-Modulen“): `app`.
* Es enthält eine Datei `app/main.py`. Da sie sich in einem Python-Package (einem Verzeichnis mit einer Datei `__init__.py`) befindet, ist sie ein „Modul“ dieses Packages: `app.main`.
@@ -99,8 +105,11 @@ Alle die gleichen Optionen werden unterstützt.
Alle die gleichen `parameters`, `responses`, `dependencies`, `tags`, usw.
!!! tip "Tipp"
In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beliebigen Namen geben.
/// tip | "Tipp"
In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beliebigen Namen geben.
///
Wir werden diesen `APIRouter` in die Hauptanwendung `FastAPI` einbinden, aber zuerst kümmern wir uns um die Abhängigkeiten und einen anderen `APIRouter`.
@@ -112,31 +121,43 @@ Also fügen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`)
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="3 6-8" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
```
```Python hl_lines="3 6-8" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1 5-7" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="1 5-7" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="1 4-6" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app/dependencies.py!}
```
//// tab | Python 3.8+ nicht annotiert
!!! tip "Tipp"
Um dieses Beispiel zu vereinfachen, verwenden wir einen erfundenen Header.
/// tip | "Tipp"
Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](security/index.md){.internal-link target=_blank} bessere Ergebnisse erzielen.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1 4-6" title="app/dependencies.py"
{!> ../../../docs_src/bigger_applications/app/dependencies.py!}
```
////
/// tip | "Tipp"
Um dieses Beispiel zu vereinfachen, verwenden wir einen erfundenen Header.
Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](security/index.md){.internal-link target=_blank} bessere Ergebnisse erzielen.
///
## Ein weiteres Modul mit `APIRouter`.
@@ -180,8 +201,11 @@ Wir können auch eine Liste von `tags` und zusätzliche `responses` hinzufügen,
Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten Request ausgeführt/aufgelöst werden.
!!! tip "Tipp"
Beachten Sie, dass ähnlich wie bei [Abhängigkeiten in *Pfadoperation-Dekoratoren*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} kein Wert an Ihre *Pfadoperation-Funktion* übergeben wird.
/// tip | "Tipp"
Beachten Sie, dass ähnlich wie bei [Abhängigkeiten in *Pfadoperation-Dekoratoren*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} kein Wert an Ihre *Pfadoperation-Funktion* übergeben wird.
///
Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten:
@@ -198,11 +222,17 @@ Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten:
* Zuerst werden die Router-Abhängigkeiten ausgeführt, dann die [`dependencies` im Dekorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} und dann die normalen Parameterabhängigkeiten.
* Sie können auch [`Security`-Abhängigkeiten mit `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} hinzufügen.
!!! tip "Tipp"
`dependencies` im `APIRouter` können beispielsweise verwendet werden, um eine Authentifizierung für eine ganze Gruppe von *Pfadoperationen* zu erfordern. Selbst wenn die Abhängigkeiten nicht jeder einzeln hinzugefügt werden.
/// tip | "Tipp"
!!! check
Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden.
`dependencies` im `APIRouter` können beispielsweise verwendet werden, um eine Authentifizierung für eine ganze Gruppe von *Pfadoperationen* zu erfordern. Selbst wenn die Abhängigkeiten nicht jeder einzeln hinzugefügt werden.
///
/// check
Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden.
///
### Die Abhängigkeiten importieren
@@ -218,8 +248,11 @@ Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
#### Wie relative Importe funktionieren
!!! tip "Tipp"
Wenn Sie genau wissen, wie Importe funktionieren, fahren Sie mit dem nächsten Abschnitt unten fort.
/// tip | "Tipp"
Wenn Sie genau wissen, wie Importe funktionieren, fahren Sie mit dem nächsten Abschnitt unten fort.
///
Ein einzelner Punkt `.`, wie in:
@@ -286,10 +319,13 @@ Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *P
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
!!! tip "Tipp"
Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`.
/// tip | "Tipp"
Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`.
Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`.
Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`.
///
## Das Haupt-`FastAPI`.
@@ -345,20 +381,23 @@ Wir könnten sie auch wie folgt importieren:
from app.routers import items, users
```
!!! info
Die erste Version ist ein „relativer Import“:
/// info
```Python
from .routers import items, users
```
Die erste Version ist ein „relativer Import“:
Die zweite Version ist ein „absoluter Import“:
```Python
from .routers import items, users
```
```Python
from app.routers import items, users
```
Die zweite Version ist ein „absoluter Import“:
Um mehr über Python-Packages und -Module zu erfahren, lesen Sie <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">die offizielle Python-Dokumentation über Module</a>.
```Python
from app.routers import items, users
```
Um mehr über Python-Packages und -Module zu erfahren, lesen Sie <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">die offizielle Python-Dokumentation über Module</a>.
///
### Namenskollisionen vermeiden
@@ -390,26 +429,35 @@ Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
{!../../../docs_src/bigger_applications/app/main.py!}
```
!!! info
`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`.
/// info
Und `items.router` enthält den `APIRouter` in der Datei `app/routers/items.py`.
`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`.
Und `items.router` enthält den `APIRouter` in der Datei `app/routers/items.py`.
///
Mit `app.include_router()` können wir jeden `APIRouter` zur Hauptanwendung `FastAPI` hinzufügen.
Es wird alle Routen von diesem Router als Teil von dieser inkludieren.
!!! note "Technische Details"
Tatsächlich wird intern eine *Pfadoperation* für jede *Pfadoperation* erstellt, die im `APIRouter` deklariert wurde.
/// note | "Technische Details"
Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles dieselbe einzige Anwendung wäre.
Tatsächlich wird intern eine *Pfadoperation* für jede *Pfadoperation* erstellt, die im `APIRouter` deklariert wurde.
!!! check
Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Performanz machen.
Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles dieselbe einzige Anwendung wäre.
Dies dauert Mikrosekunden und geschieht nur beim Start.
///
Es hat also keinen Einfluss auf die Leistung. ⚡
/// check
Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Performanz machen.
Dies dauert Mikrosekunden und geschieht nur beim Start.
Es hat also keinen Einfluss auf die Leistung. ⚡
///
### Einen `APIRouter` mit benutzerdefinierten `prefix`, `tags`, `responses` und `dependencies` einfügen
@@ -456,16 +504,19 @@ Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
!!! info "Sehr technische Details"
**Hinweis**: Dies ist ein sehr technisches Detail, das Sie wahrscheinlich **einfach überspringen** können.
/// info | "Sehr technische Details"
---
**Hinweis**: Dies ist ein sehr technisches Detail, das Sie wahrscheinlich **einfach überspringen** können.
Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert.
---
Das liegt daran, dass wir deren *Pfadoperationen* in das OpenAPI-Schema und die Benutzeroberflächen einbinden möchten.
Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert.
Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ können, werden die *Pfadoperationen* „geklont“ (neu erstellt) und nicht direkt einbezogen.
Das liegt daran, dass wir deren *Pfadoperationen* in das OpenAPI-Schema und die Benutzeroberflächen einbinden möchten.
Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ können, werden die *Pfadoperationen* „geklont“ (neu erstellt) und nicht direkt einbezogen.
///
## Es in der automatischen API-Dokumentation ansehen
+103 -59
View File
@@ -6,98 +6,139 @@ So wie Sie zusätzliche Validation und Metadaten in Parametern der **Pfadoperati
Importieren Sie es zuerst:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
```
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
```
```Python hl_lines="2"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! warning "Achtung"
Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fastapi`, wie die anderen (`Query`, `Path`, `Body`, usw.)
///
```Python hl_lines="2"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
////
/// warning | "Achtung"
Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fastapi`, wie die anderen (`Query`, `Path`, `Body`, usw.)
///
## Modellattribute deklarieren
Dann können Sie `Field` mit Modellattributen deklarieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
```
```Python hl_lines="12-15"
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="12-15"
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
```
```Python hl_lines="9-12"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9-12"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
////
`Field` funktioniert genauso wie `Query`, `Path` und `Body`, es hat die gleichen Parameter, usw.
!!! note "Technische Details"
Tatsächlich erstellen `Query`, `Path` und andere, die sie kennenlernen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, die ihrerseits eine Unterklasse von Pydantics `FieldInfo`-Klasse ist.
/// note | "Technische Details"
Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück.
Tatsächlich erstellen `Query`, `Path` und andere, die sie kennenlernen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, die ihrerseits eine Unterklasse von Pydantics `FieldInfo`-Klasse ist.
`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück.
Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
!!! tip "Tipp"
Beachten Sie, dass jedes Modellattribut mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer Pfadoperation-Funktion, nur mit `Field` statt `Path`, `Query`, `Body`.
Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
///
/// tip | "Tipp"
Beachten Sie, dass jedes Modellattribut mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer Pfadoperation-Funktion, nur mit `Field` statt `Path`, `Query`, `Body`.
///
## Zusätzliche Information hinzufügen
@@ -105,8 +146,11 @@ Sie können zusätzliche Information in `Field`, `Query`, `Body`, usw. deklarier
Sie werden später mehr darüber lernen, wie man zusätzliche Information unterbringt, wenn Sie lernen, Beispiele zu deklarieren.
!!! warning "Achtung"
Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel nicht notwendigerweise Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren.
/// warning | "Achtung"
Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel nicht notwendigerweise Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren.
///
## Zusammenfassung
+187 -110
View File
@@ -8,44 +8,63 @@ Zuerst einmal, Sie können `Path`-, `Query`- und Requestbody-Parameter-Deklarati
Und Sie können auch Body-Parameter als optional kennzeichnen, indem Sie den Defaultwert auf `None` setzen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
```
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
```
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
```
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! note "Hinweis"
Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, optional ist. Da es `None` als Defaultwert hat.
///
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
```
////
/// note | "Hinweis"
Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, optional ist. Da es `None` als Defaultwert hat.
///
## Mehrere Body-Parameter
@@ -62,17 +81,21 @@ Im vorherigen Beispiel erwartete die *Pfadoperation* einen JSON-Body mit den Att
Aber Sie können auch mehrere Body-Parameter deklarieren, z. B. `item` und `user`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
```
////
In diesem Fall wird **FastAPI** bemerken, dass es mehr als einen Body-Parameter in der Funktion gibt (zwei Parameter, die Pydantic-Modelle sind).
@@ -93,8 +116,11 @@ Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden,
}
```
!!! note "Hinweis"
Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem Schlüssel `item` im Body erwartet wird.
/// note | "Hinweis"
Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem Schlüssel `item` im Body erwartet wird.
///
**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, genau so wie der Parameter `user`.
@@ -110,41 +136,57 @@ Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, das
Aber Sie können **FastAPI** instruieren, ihn als weiteren Body-Schlüssel zu erkennen, indem Sie `Body` verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
```
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
```
```Python hl_lines="24"
{!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="24"
{!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
////
In diesem Fall erwartet **FastAPI** einen Body wie:
@@ -184,44 +226,63 @@ q: str | None = None
Zum Beispiel:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
```
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
```
```Python hl_lines="28"
{!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="28"
{!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
```
```Python hl_lines="25"
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! info
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen.
///
```Python hl_lines="25"
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
```
////
/// info
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen.
///
## Einen einzelnen Body-Parameter einbetten
@@ -237,41 +298,57 @@ item: Item = Body(embed=True)
so wie in:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
```
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
```
```Python hl_lines="18"
{!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="18"
{!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
```
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
```
////
In diesem Fall erwartet **FastAPI** einen Body wie:
+180 -117
View File
@@ -6,17 +6,21 @@ Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle
Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`e.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
```
//// tab | Python 3.8+
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
```
////
Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der Elemente der Liste aussagt.
@@ -61,23 +65,29 @@ Verwenden Sie dieselbe Standardsyntax für Modellattribute mit inneren Typen.
In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Liste von Strings“ ist:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
```
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
////
## Set-Typen
@@ -87,23 +97,29 @@ Python hat einen Datentyp speziell für Mengen eindeutiger Dinge: das <abbr titl
Deklarieren wir also `tags` als Set von Strings.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
```
```Python hl_lines="1 14"
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 14"
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
```
////
Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert.
@@ -125,45 +141,57 @@ Alles das beliebig tief verschachtelt.
Wir können zum Beispiel ein `Image`-Modell definieren.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7-9"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
```Python hl_lines="7-9"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
////
### Das Kindmodell als Typ verwenden
Und dann können wir es als Typ eines Attributes verwenden.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
////
Das würde bedeuten, dass **FastAPI** einen Body erwartet wie:
@@ -196,23 +224,29 @@ Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich <a href="https:
Da wir zum Beispiel im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="2 8"
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```
```Python hl_lines="2 8"
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
```
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
```
////
Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in JSON Schema / OpenAPI dokumentiert.
@@ -220,23 +254,29 @@ Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in
Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
```
////
Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie:
@@ -264,33 +304,45 @@ Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie
}
```
!!! info
Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat.
/// info
Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat.
///
## Tief verschachtelte Modelle
Sie können beliebig tief verschachtelte Modelle definieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7 12 18 21 25"
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```
```Python hl_lines="7 12 18 21 25"
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
```
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
```
////
!!! info
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat.
//// tab | Python 3.8+
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
```
////
/// info
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat.
///
## Bodys aus reinen Listen
@@ -308,17 +360,21 @@ images: list[Image]
so wie in:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="13"
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
```
```Python hl_lines="13"
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="15"
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
```
//// tab | Python 3.8+
```Python hl_lines="15"
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
```
////
## Editor-Unterstützung überall
@@ -348,26 +404,33 @@ Das schauen wir uns mal an.
Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="7"
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
```
//// tab | Python 3.8+
!!! tip "Tipp"
Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt.
```Python hl_lines="9"
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
```
Aber Pydantic hat automatische Datenkonvertierung.
////
Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren.
/// tip | "Tipp"
Und das `dict` welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben.
Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt.
Aber Pydantic hat automatische Datenkonvertierung.
Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren.
Und das `dict` welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben.
///
## Zusammenfassung
+105 -66
View File
@@ -6,23 +6,29 @@ Um einen Artikel zu aktualisieren, können Sie die <a href="https://developer.mo
Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (in z. B. einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="28-33"
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```
```Python hl_lines="28-33"
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
```
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001.py!}
```
////
`PUT` wird verwendet, um Daten zu empfangen, die die existierenden Daten ersetzen sollen.
@@ -48,14 +54,17 @@ Sie können auch die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/
Das bedeutet, sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert.
!!! note "Hinweis"
`PATCH` wird seltener verwendet und ist weniger bekannt als `PUT`.
/// note | "Hinweis"
Und viele Teams verwenden ausschließlich `PUT`, selbst für nur Teil-Aktualisierungen.
`PATCH` wird seltener verwendet und ist weniger bekannt als `PUT`.
Es steht Ihnen **frei**, das zu verwenden, was Sie möchten, **FastAPI** legt Ihnen keine Einschränkungen auf.
Und viele Teams verwenden ausschließlich `PUT`, selbst für nur Teil-Aktualisierungen.
Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweise verwendet werden.
Es steht Ihnen **frei**, das zu verwenden, was Sie möchten, **FastAPI** legt Ihnen keine Einschränkungen auf.
Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweise verwendet werden.
///
### Pydantics `exclude_unset`-Parameter verwenden
@@ -63,61 +72,79 @@ Wenn Sie Teil-Aktualisierungen entgegennehmen, ist der `exclude_unset`-Parameter
Wie in `item.model_dump(exclude_unset=True)`.
!!! info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
/// info
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
///
Das wird ein `dict` erstellen, mit nur den Daten, die gesetzt wurden als das `item`-Modell erstellt wurde, Defaultwerte ausgeschlossen.
Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im Request) gesendeten Daten enthält, ohne Defaultwerte:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="32"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
```Python hl_lines="32"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
////
### Pydantics `update`-Parameter verwenden
Jetzt können Sie eine Kopie des existierenden Modells mittels `.model_copy()` erstellen, wobei Sie dem `update`-Parameter ein `dict` mit den zu ändernden Daten übergeben.
!!! info
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt.
/// info
Die Beispiele hier verwenden `.copy()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_copy()` verwenden, wenn Sie Pydantic v2 verwenden können.
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt.
Die Beispiele hier verwenden `.copy()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_copy()` verwenden, wenn Sie Pydantic v2 verwenden können.
///
Wie in `stored_item_model.model_copy(update=update_data)`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="33"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
```Python hl_lines="33"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
////
### Rekapitulation zum teilweisen Ersetzen
@@ -134,32 +161,44 @@ Zusammengefasst, um Teil-Ersetzungen vorzunehmen:
* Speichern Sie die Daten in Ihrer Datenbank.
* Geben Sie das aktualisierte Modell zurück.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="28-35"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
```Python hl_lines="28-35"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
////
!!! tip "Tipp"
Sie können tatsächlich die gleiche Technik mit einer HTTP `PUT` Operation verwenden.
//// tab | Python 3.8+
Aber dieses Beispiel verwendet `PATCH`, da dieses für solche Anwendungsfälle geschaffen wurde.
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
!!! note "Hinweis"
Beachten Sie, dass das hereinkommende Modell immer noch validiert wird.
////
Wenn Sie also Teil-Aktualisierungen empfangen wollen, die alle Attribute auslassen können, müssen Sie ein Modell haben, dessen Attribute alle als optional gekennzeichnet sind (mit Defaultwerten oder `None`).
/// tip | "Tipp"
Um zu unterscheiden zwischen Modellen für **Aktualisierungen**, mit lauter optionalen Werten, und solchen für die **Erzeugung**, mit benötigten Werten, können Sie die Techniken verwenden, die in [Extramodelle](extra-models.md){.internal-link target=_blank} beschrieben wurden.
Sie können tatsächlich die gleiche Technik mit einer HTTP `PUT` Operation verwenden.
Aber dieses Beispiel verwendet `PATCH`, da dieses für solche Anwendungsfälle geschaffen wurde.
///
/// note | "Hinweis"
Beachten Sie, dass das hereinkommende Modell immer noch validiert wird.
Wenn Sie also Teil-Aktualisierungen empfangen wollen, die alle Attribute auslassen können, müssen Sie ein Modell haben, dessen Attribute alle als optional gekennzeichnet sind (mit Defaultwerten oder `None`).
Um zu unterscheiden zwischen Modellen für **Aktualisierungen**, mit lauter optionalen Werten, und solchen für die **Erzeugung**, mit benötigten Werten, können Sie die Techniken verwenden, die in [Extramodelle](extra-models.md){.internal-link target=_blank} beschrieben wurden.
///
+96 -63
View File
@@ -8,28 +8,35 @@ Ihre API sendet fast immer einen **Response**body. Aber Clients senden nicht unb
Um einen **Request**body zu deklarieren, verwenden Sie <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>-Modelle mit allen deren Fähigkeiten und Vorzügen.
!!! info
Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
/// info
Senden Sie einen Body mit einem `GET`-Request, dann führt das laut Spezifikation zu undefiniertem Verhalten. Trotzdem wird es von FastAPI unterstützt, für sehr komplexe/extreme Anwendungsfälle.
Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
Da aber davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body auch nicht an, wenn `GET` verwendet wird. Dazwischengeschaltete Proxys unterstützen es möglicherweise auch nicht.
Senden Sie einen Body mit einem `GET`-Request, dann führt das laut Spezifikation zu undefiniertem Verhalten. Trotzdem wird es von FastAPI unterstützt, für sehr komplexe/extreme Anwendungsfälle.
Da aber davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body auch nicht an, wenn `GET` verwendet wird. Dazwischengeschaltete Proxys unterstützen es möglicherweise auch nicht.
///
## Importieren Sie Pydantics `BaseModel`
Zuerst müssen Sie `BaseModel` von `pydantic` importieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="2"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
```Python hl_lines="2"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="4"
{!> ../../../docs_src/body/tutorial001.py!}
```
//// tab | Python 3.8+
```Python hl_lines="4"
{!> ../../../docs_src/body/tutorial001.py!}
```
////
## Erstellen Sie Ihr Datenmodell
@@ -37,17 +44,21 @@ Dann deklarieren Sie Ihr Datenmodell als eine Klasse, die von `BaseModel` erbt.
Verwenden Sie Standard-Python-Typen für die Klassenattribute:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="5-9"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
```Python hl_lines="5-9"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="7-11"
{!> ../../../docs_src/body/tutorial001.py!}
```
//// tab | Python 3.8+
```Python hl_lines="7-11"
{!> ../../../docs_src/body/tutorial001.py!}
```
////
Wie auch bei Query-Parametern gilt, wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Ansonsten ist es erforderlich. Verwenden Sie `None`, um es als optional zu kennzeichnen.
@@ -75,17 +86,21 @@ Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre fol
Um es zu Ihrer *Pfadoperation* hinzuzufügen, deklarieren Sie es auf die gleiche Weise, wie Sie Pfad- und Query-Parameter deklariert haben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial001.py!}
```
//// tab | Python 3.8+
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial001.py!}
```
////
... und deklarieren Sie seinen Typ als das Modell, welches Sie erstellt haben, `Item`.
@@ -134,32 +149,39 @@ Aber Sie bekommen die gleiche Editor-Unterstützung in <a href="https://www.jetb
<img src="/img/tutorial/body/image05.png">
!!! tip "Tipp"
Wenn Sie <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> als Ihren Editor verwenden, probieren Sie das <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> aus.
/// tip | "Tipp"
Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit:
Wenn Sie <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> als Ihren Editor verwenden, probieren Sie das <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> aus.
* Code-Vervollständigung
* Typüberprüfungen
* Refaktorisierung
* Suchen
* Inspektionen
Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit:
* Code-Vervollständigung
* Typüberprüfungen
* Refaktorisierung
* Suchen
* Inspektionen
///
## Das Modell verwenden
Innerhalb der Funktion können Sie alle Attribute des Modells direkt verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../../docs_src/body/tutorial002_py310.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/body/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="21"
{!> ../../../docs_src/body/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="21"
{!> ../../../docs_src/body/tutorial002.py!}
```
////
## Requestbody- + Pfad-Parameter
@@ -167,17 +189,21 @@ Sie können Pfad- und Requestbody-Parameter gleichzeitig deklarieren.
**FastAPI** erkennt, dass Funktionsparameter, die mit Pfad-Parametern übereinstimmen, **vom Pfad genommen** werden sollen, und dass Funktionsparameter, welche Pydantic-Modelle sind, **vom Requestbody genommen** werden sollen.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="15-16"
{!> ../../../docs_src/body/tutorial003_py310.py!}
```
```Python hl_lines="15-16"
{!> ../../../docs_src/body/tutorial003_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="17-18"
{!> ../../../docs_src/body/tutorial003.py!}
```
//// tab | Python 3.8+
```Python hl_lines="17-18"
{!> ../../../docs_src/body/tutorial003.py!}
```
////
## Requestbody- + Pfad- + Query-Parameter
@@ -185,17 +211,21 @@ Sie können auch zur gleichen Zeit **Body-**, **Pfad-** und **Query-Parameter**
**FastAPI** wird jeden Parameter korrekt erkennen und die Daten vom richtigen Ort holen.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial004_py310.py!}
```
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial004_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial004.py!}
```
//// tab | Python 3.8+
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial004.py!}
```
////
Die Funktionsparameter werden wie folgt erkannt:
@@ -203,10 +233,13 @@ Die Funktionsparameter werden wie folgt erkannt:
* Wenn der Parameter ein **einfacher Typ** ist (wie `int`, `float`, `str`, `bool`, usw.), wird er als **Query**-Parameter interpretiert.
* Wenn der Parameter vom Typ eines **Pydantic-Modells** ist, wird er als Request**body** interpretiert.
!!! note "Hinweis"
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, wegen des definierten Defaultwertes `= None`
/// note | "Hinweis"
Das `Union` in `Union[str, None]` wird von FastAPI nicht verwendet, aber es erlaubt Ihrem Editor, Sie besser zu unterstützen und Fehler zu erkennen.
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, wegen des definierten Defaultwertes `= None`
Das `Union` in `Union[str, None]` wird von FastAPI nicht verwendet, aber es erlaubt Ihrem Editor, Sie besser zu unterstützen und Fehler zu erkennen.
///
## Ohne Pydantic
+91 -53
View File
@@ -6,41 +6,57 @@ So wie `Query`- und `Path`-Parameter können Sie auch <abbr title='Cookie –
Importieren Sie zuerst `Cookie`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
```
```Python hl_lines="1"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
////
## `Cookie`-Parameter deklarieren
@@ -48,49 +64,71 @@ Dann deklarieren Sie Ihre Cookie-Parameter, auf die gleiche Weise, wie Sie auch
Der erste Wert ist der Typ. Sie können `Cookie` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10"
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! note "Technische Details"
`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
///
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
```Python hl_lines="7"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
!!! info
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
////
/// note | "Technische Details"
`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
///
/// info
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
///
## Zusammenfassung
@@ -6,41 +6,57 @@ Bevor wir tiefer in das **Dependency Injection** System eintauchen, lassen Sie u
Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
////
Aber dann haben wir ein `dict` im Parameter `commons` der *Pfadoperation-Funktion*.
@@ -103,117 +119,165 @@ Das gilt auch für Callables ohne Parameter. So wie es auch für *Pfadoperation-
Dann können wir das „Dependable“ `common_parameters` der Abhängigkeit von oben in die Klasse `CommonQueryParams` ändern:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
```Python hl_lines="12-16"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="12-16"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
////
Achten Sie auf die Methode `__init__`, die zum Erstellen der Instanz der Klasse verwendet wird:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
////
... sie hat die gleichen Parameter wie unsere vorherige `common_parameters`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="8"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
////
Diese Parameter werden von **FastAPI** verwendet, um die Abhängigkeit „aufzulösen“.
@@ -229,41 +293,57 @@ In beiden Fällen werden die Daten konvertiert, validiert, im OpenAPI-Schema dok
Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
////
**FastAPI** ruft die Klasse `CommonQueryParams` auf. Dadurch wird eine „Instanz“ dieser Klasse erstellt und die Instanz wird als Parameter `commons` an Ihre Funktion überreicht.
@@ -271,20 +351,27 @@ Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
////
Das letzte `CommonQueryParams`, in:
@@ -300,77 +387,107 @@ Aus diesem extrahiert FastAPI die deklarierten Parameter, und dieses ist es, was
In diesem Fall hat das erste `CommonQueryParams` in:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[CommonQueryParams, ...
```
```Python
commons: Annotated[CommonQueryParams, ...
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python
commons: CommonQueryParams ...
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons: CommonQueryParams ...
```
////
... keine besondere Bedeutung für **FastAPI**. FastAPI verwendet es nicht für die Datenkonvertierung, -validierung, usw. (da es dafür `Depends(CommonQueryParams)` verwendet).
Sie könnten tatsächlich einfach schreiben:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
```
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python
commons = Depends(CommonQueryParams)
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons = Depends(CommonQueryParams)
```
////
... wie in:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial003_an.py!}
```
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
```
////
Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was als Parameter `commons` übergeben wird, und Ihnen dann bei der Codevervollständigung, Typprüfungen, usw. helfen kann:
@@ -380,20 +497,27 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was al
Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
////
**FastAPI** bietet eine Abkürzung für diese Fälle, wo die Abhängigkeit *speziell* eine Klasse ist, welche **FastAPI** aufruft, um eine Instanz der Klasse selbst zu erstellen.
@@ -401,81 +525,114 @@ In diesem speziellen Fall können Sie Folgendes tun:
Anstatt zu schreiben:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
////
... schreiben Sie:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python
commons: Annotated[CommonQueryParams, Depends()]
```
```Python
commons: Annotated[CommonQueryParams, Depends()]
```
=== "Python 3.8 nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8 nicht annotiert
```Python
commons: CommonQueryParams = Depends()
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
commons: CommonQueryParams = Depends()
```
////
Sie deklarieren die Abhängigkeit als Typ des Parameters und verwenden `Depends()` ohne Parameter, anstatt die vollständige Klasse *erneut* in `Depends(CommonQueryParams)` schreiben zu müssen.
Dasselbe Beispiel würde dann so aussehen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
```
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial004_an.py!}
```
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
////
... und **FastAPI** wird wissen, was zu tun ist.
!!! tip "Tipp"
Wenn Sie das eher verwirrt, als Ihnen zu helfen, ignorieren Sie es, Sie *brauchen* es nicht.
/// tip | "Tipp"
Es ist nur eine Abkürzung. Es geht **FastAPI** darum, Ihnen dabei zu helfen, Codeverdoppelung zu minimieren.
Wenn Sie das eher verwirrt, als Ihnen zu helfen, ignorieren Sie es, Sie *brauchen* es nicht.
Es ist nur eine Abkürzung. Es geht **FastAPI** darum, Ihnen dabei zu helfen, Codeverdoppelung zu minimieren.
///
@@ -14,40 +14,55 @@ Der *Pfadoperation-Dekorator* erhält ein optionales Argument `dependencies`.
Es sollte eine `list`e von `Depends()` sein:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="18"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8 nicht annotiert"
```Python hl_lines="18"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
////
Diese Abhängigkeiten werden auf die gleiche Weise wie normale Abhängigkeiten ausgeführt/aufgelöst. Aber ihr Wert (falls sie einen zurückgeben) wird nicht an Ihre *Pfadoperation-Funktion* übergeben.
!!! tip "Tipp"
Einige Editoren prüfen, ob Funktionsparameter nicht verwendet werden, und zeigen das als Fehler an.
/// tip | "Tipp"
Wenn Sie `dependencies` im *Pfadoperation-Dekorator* verwenden, stellen Sie sicher, dass sie ausgeführt werden, während gleichzeitig Ihr Editor/Ihre Tools keine Fehlermeldungen ausgeben.
Einige Editoren prüfen, ob Funktionsparameter nicht verwendet werden, und zeigen das als Fehler an.
Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die einen nicht verwendeten Parameter in Ihrem Code sehen und ihn für unnötig halten könnten.
Wenn Sie `dependencies` im *Pfadoperation-Dekorator* verwenden, stellen Sie sicher, dass sie ausgeführt werden, während gleichzeitig Ihr Editor/Ihre Tools keine Fehlermeldungen ausgeben.
!!! info
In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`.
Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die einen nicht verwendeten Parameter in Ihrem Code sehen und ihn für unnötig halten könnten.
Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr Vorteile durch die Verwendung der integrierten [Sicherheits-Werkzeuge (siehe nächstes Kapitel)](../security/index.md){.internal-link target=_blank} erzielen.
///
/// info
In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`.
Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr Vorteile durch die Verwendung der integrierten [Sicherheits-Werkzeuge (siehe nächstes Kapitel)](../security/index.md){.internal-link target=_blank} erzielen.
///
## Abhängigkeitsfehler und -Rückgabewerte
@@ -57,51 +72,69 @@ Sie können dieselben Abhängigkeits-*Funktionen* verwenden, die Sie normalerwei
Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="7 12"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8 nicht annotiert"
```Python hl_lines="7 12"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="6 11"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="6 11"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
////
### Exceptions auslösen
Die Abhängigkeiten können Exceptions `raise`n, genau wie normale Abhängigkeiten:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8 nicht annotiert"
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
////
### Rückgabewerte
@@ -109,26 +142,35 @@ Und sie können Werte zurückgeben oder nicht, die Werte werden nicht verwendet.
Sie können also eine normale Abhängigkeit (die einen Wert zurückgibt), die Sie bereits an anderer Stelle verwenden, wiederverwenden, und auch wenn der Wert nicht verwendet wird, wird die Abhängigkeit ausgeführt:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8 nicht annotiert"
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
////
## Abhängigkeiten für eine Gruppe von *Pfadoperationen*
@@ -4,18 +4,24 @@ FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige <abbr title="Man
Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte / den zusätzlichen Code danach.
!!! tip "Tipp"
Stellen Sie sicher, dass Sie `yield` nur einmal pro Abhängigkeit verwenden.
/// tip | "Tipp"
!!! note "Technische Details"
Jede Funktion, die dekoriert werden kann mit:
Stellen Sie sicher, dass Sie `yield` nur einmal pro Abhängigkeit verwenden.
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
///
kann auch als gültige **FastAPI**-Abhängigkeit verwendet werden.
/// note | "Technische Details"
Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern.
Jede Funktion, die dekoriert werden kann mit:
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
kann auch als gültige **FastAPI**-Abhängigkeit verwendet werden.
Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern.
///
## Eine Datenbank-Abhängigkeit mit `yield`.
@@ -39,10 +45,13 @@ Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Respon
{!../../../docs_src/dependencies/tutorial007.py!}
```
!!! tip "Tipp"
Sie können `async`hrone oder reguläre Funktionen verwenden.
/// tip | "Tipp"
**FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten.
Sie können `async`hrone oder reguläre Funktionen verwenden.
**FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten.
///
## Eine Abhängigkeit mit `yield` und `try`.
@@ -66,26 +75,35 @@ Sie können Unterabhängigkeiten und „Bäume“ von Unterabhängigkeiten belie
Beispielsweise kann `dependency_c` von `dependency_b` und `dependency_b` von `dependency_a` abhängen:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="6 14 22"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
```Python hl_lines="6 14 22"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="5 13 21"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="5 13 21"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="4 12 20"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="4 12 20"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
////
Und alle können `yield` verwenden.
@@ -93,26 +111,35 @@ In diesem Fall benötigt `dependency_c` zum Ausführen seines Exit-Codes, dass d
Und wiederum benötigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` genannt) für seinen Exit-Code.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="18-19 26-27"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
```Python hl_lines="18-19 26-27"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="17-18 25-26"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="17-18 25-26"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="16-17 24-25"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="16-17 24-25"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
////
Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und alle können beliebig voneinander abhängen.
@@ -122,10 +149,13 @@ Sie können beliebige Kombinationen von Abhängigkeiten haben.
**FastAPI** stellt sicher, dass alles in der richtigen Reihenfolge ausgeführt wird.
!!! note "Technische Details"
Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">Kontextmanager</a>.
/// note | "Technische Details"
**FastAPI** verwendet sie intern, um das zu erreichen.
Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">Kontextmanager</a>.
**FastAPI** verwendet sie intern, um das zu erreichen.
///
## Abhängigkeiten mit `yield` und `HTTPException`.
@@ -133,32 +163,43 @@ Sie haben gesehen, dass Ihre Abhängigkeiten `yield` verwenden können und `try`
Auf die gleiche Weise könnten Sie im Exit-Code nach dem `yield` eine `HTTPException` oder ähnliches auslösen.
!!! tip "Tipp"
/// tip | "Tipp"
Dies ist eine etwas fortgeschrittene Technik, die Sie in den meisten Fällen nicht wirklich benötigen, da Sie Exceptions (einschließlich `HTTPException`) innerhalb des restlichen Anwendungscodes auslösen können, beispielsweise in der *Pfadoperation-Funktion*.
Dies ist eine etwas fortgeschrittene Technik, die Sie in den meisten Fällen nicht wirklich benötigen, da Sie Exceptions (einschließlich `HTTPException`) innerhalb des restlichen Anwendungscodes auslösen können, beispielsweise in der *Pfadoperation-Funktion*.
Aber es ist für Sie da, wenn Sie es brauchen. 🤓
Aber es ist für Sie da, wenn Sie es brauchen. 🤓
=== "Python 3.9+"
///
```Python hl_lines="18-22 31"
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="18-22 31"
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!}
```
```Python hl_lines="17-21 30"
{!> ../../../docs_src/dependencies/tutorial008b_an.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="17-21 30"
{!> ../../../docs_src/dependencies/tutorial008b_an.py!}
```
```Python hl_lines="16-20 29"
{!> ../../../docs_src/dependencies/tutorial008b.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="16-20 29"
{!> ../../../docs_src/dependencies/tutorial008b.py!}
```
////
Eine Alternative zum Abfangen von Exceptions (und möglicherweise auch zum Auslösen einer weiteren `HTTPException`) besteht darin, einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} zu erstellen.
@@ -201,22 +242,31 @@ participant tasks as Hintergrundtasks
end
```
!!! info
Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein.
/// info
Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesendet werden.
Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein.
!!! tip "Tipp"
Obiges Diagramm verwendet `HTTPException`, aber Sie können auch jede andere Exception auslösen, die Sie in einer Abhängigkeit mit `yield` abfangen, oder mit einem [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} erstellt haben.
Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesendet werden.
Wenn Sie eine Exception auslösen, wird diese mit yield an die Abhängigkeiten übergeben, einschließlich `HTTPException`, und dann **erneut** an die Exceptionhandler. Wenn es für diese Exception keinen Exceptionhandler gibt, wird sie von der internen Default-`ServerErrorMiddleware` gehandhabt, was einen HTTP-Statuscode 500 zurückgibt, um den Client darüber zu informieren, dass ein Fehler auf dem Server aufgetreten ist.
///
/// tip | "Tipp"
Obiges Diagramm verwendet `HTTPException`, aber Sie können auch jede andere Exception auslösen, die Sie in einer Abhängigkeit mit `yield` abfangen, oder mit einem [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} erstellt haben.
Wenn Sie eine Exception auslösen, wird diese mit yield an die Abhängigkeiten übergeben, einschließlich `HTTPException`, und dann **erneut** an die Exceptionhandler. Wenn es für diese Exception keinen Exceptionhandler gibt, wird sie von der internen Default-`ServerErrorMiddleware` gehandhabt, was einen HTTP-Statuscode 500 zurückgibt, um den Client darüber zu informieren, dass ein Fehler auf dem Server aufgetreten ist.
///
## Abhängigkeiten mit `yield`, `HTTPException` und Hintergrundtasks
!!! warning "Achtung"
Sie benötigen diese technischen Details höchstwahrscheinlich nicht, Sie können diesen Abschnitt überspringen und weiter unten fortfahren.
/// warning | "Achtung"
Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI vor 0.106.0 verwendet haben und Ressourcen aus Abhängigkeiten mit `yield` in Hintergrundtasks verwendet haben.
Sie benötigen diese technischen Details höchstwahrscheinlich nicht, Sie können diesen Abschnitt überspringen und weiter unten fortfahren.
Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI vor 0.106.0 verwendet haben und Ressourcen aus Abhängigkeiten mit `yield` in Hintergrundtasks verwendet haben.
///
Vor FastAPI 0.106.0 war das Auslösen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, *nachdem* die Response gesendet wurde, die [Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} wären also bereits ausgeführt worden.
@@ -224,11 +274,13 @@ Dies wurde hauptsächlich so konzipiert, damit die gleichen Objekte, die durch A
Da dies jedoch bedeuten würde, darauf zu warten, dass die Response durch das Netzwerk reist, während eine Ressource unnötigerweise in einer Abhängigkeit mit yield gehalten wird (z. B. eine Datenbankverbindung), wurde dies in FastAPI 0.106.0 geändert.
!!! tip "Tipp"
/// tip | "Tipp"
Darüber hinaus handelt es sich bei einem Hintergrundtask normalerweise um einen unabhängigen Satz von Logik, der separat behandelt werden sollte, mit eigenen Ressourcen (z. B. einer eigenen Datenbankverbindung).
Darüber hinaus handelt es sich bei einem Hintergrundtask normalerweise um einen unabhängigen Satz von Logik, der separat behandelt werden sollte, mit eigenen Ressourcen (z. B. einer eigenen Datenbankverbindung).
Auf diese Weise erhalten Sie wahrscheinlich saubereren Code.
Auf diese Weise erhalten Sie wahrscheinlich saubereren Code.
///
Wenn Sie sich früher auf dieses Verhalten verlassen haben, sollten Sie jetzt die Ressourcen für Hintergrundtasks innerhalb des Hintergrundtasks selbst erstellen und intern nur Daten verwenden, die nicht von den Ressourcen von Abhängigkeiten mit `yield` abhängen.
@@ -256,10 +308,13 @@ Wenn Sie eine Abhängigkeit mit `yield` erstellen, erstellt **FastAPI** dafür i
### Kontextmanager in Abhängigkeiten mit `yield` verwenden
!!! warning "Achtung"
Dies ist mehr oder weniger eine „fortgeschrittene“ Idee.
/// warning | "Achtung"
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorerst überspringen.
Dies ist mehr oder weniger eine „fortgeschrittene“ Idee.
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorerst überspringen.
///
In Python können Sie Kontextmanager erstellen, indem Sie <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">eine Klasse mit zwei Methoden erzeugen: `__enter__()` und `__exit__()`</a>.
@@ -269,16 +324,19 @@ Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` ve
{!../../../docs_src/dependencies/tutorial010.py!}
```
!!! tip "Tipp"
Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind:
/// tip | "Tipp"
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind:
Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat.
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet.
Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat.
Aber Sie müssen die Dekoratoren nicht für FastAPI-Abhängigkeiten verwenden (und das sollten Sie auch nicht).
Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet.
FastAPI erledigt das intern für Sie.
Aber Sie müssen die Dekoratoren nicht für FastAPI-Abhängigkeiten verwenden (und das sollten Sie auch nicht).
FastAPI erledigt das intern für Sie.
///
@@ -6,26 +6,35 @@ Bei einigen Anwendungstypen möchten Sie möglicherweise Abhängigkeiten zur ges
In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
```
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8 nicht annotiert"
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="15"
{!> ../../../docs_src/dependencies/tutorial012.py!}
```
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="15"
{!> ../../../docs_src/dependencies/tutorial012.py!}
```
////
Und alle Ideen aus dem Abschnitt über das [Hinzufügen von `dependencies` zu den *Pfadoperation-Dekoratoren*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} gelten weiterhin, aber in diesem Fall für alle *Pfadoperationen* in der Anwendung.
+167 -98
View File
@@ -30,41 +30,57 @@ Aber so können wir uns besser auf die Funktionsweise des **Dependency Injection
Konzentrieren wir uns zunächst auf die Abhängigkeit - die Dependency.
Es handelt sich einfach um eine Funktion, die die gleichen Parameter entgegennimmt wie eine *Pfadoperation-Funktion*:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
```Python hl_lines="9-12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="9-12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
////
Das war's schon.
@@ -84,90 +100,125 @@ In diesem Fall erwartet diese Abhängigkeit:
Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält.
!!! info
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
/// info
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
///
### `Depends` importieren
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
```Python hl_lines="1"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
////
### Deklarieren der Abhängigkeit im <abbr title="Das Abhängige, der Verwender der Abhängigkeit">„Dependant“</abbr>
So wie auch `Body`, `Query`, usw., verwenden Sie `Depends` mit den Parametern Ihrer *Pfadoperation-Funktion*:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="13 18"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
```Python hl_lines="13 18"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
```Python hl_lines="16 21"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="16 21"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
////
Obwohl Sie `Depends` in den Parametern Ihrer Funktion genauso verwenden wie `Body`, `Query`, usw., funktioniert `Depends` etwas anders.
@@ -179,8 +230,11 @@ Sie **rufen diese nicht direkt auf** (fügen Sie am Ende keine Klammern hinzu),
Und diese Funktion akzeptiert Parameter auf die gleiche Weise wie *Pfadoperation-Funktionen*.
!!! tip "Tipp"
Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen, Sie als Abhängigkeiten verwenden können.
/// tip | "Tipp"
Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen, Sie als Abhängigkeiten verwenden können.
///
Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum:
@@ -201,10 +255,13 @@ common_parameters --> read_users
Auf diese Weise schreiben Sie gemeinsam genutzten Code nur einmal, und **FastAPI** kümmert sich darum, ihn für Ihre *Pfadoperationen* aufzurufen.
!!! check
Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich.
/// check
Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erledigt wird.
Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich.
Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erledigt wird.
///
## `Annotated`-Abhängigkeiten wiederverwenden
@@ -218,28 +275,37 @@ commons: Annotated[dict, Depends(common_parameters)]
Da wir jedoch `Annotated` verwenden, können wir diesen `Annotated`-Wert in einer Variablen speichern und an mehreren Stellen verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="12 16 21"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
```
```Python hl_lines="12 16 21"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="14 18 23"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="14 18 23"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
```
```Python hl_lines="15 19 24"
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
```
////
!!! tip "Tipp"
Das ist schlicht Standard-Python, es wird als „Typalias“ bezeichnet und ist eigentlich nicht **FastAPI**-spezifisch.
//// tab | Python 3.8+
Da **FastAPI** jedoch auf Standard-Python, einschließlich `Annotated`, basiert, können Sie diesen Trick in Ihrem Code verwenden. 😎
```Python hl_lines="15 19 24"
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
```
////
/// tip | "Tipp"
Das ist schlicht Standard-Python, es wird als „Typalias“ bezeichnet und ist eigentlich nicht **FastAPI**-spezifisch.
Da **FastAPI** jedoch auf Standard-Python, einschließlich `Annotated`, basiert, können Sie diesen Trick in Ihrem Code verwenden. 😎
///
Die Abhängigkeiten funktionieren weiterhin wie erwartet, und das **Beste daran** ist, dass die **Typinformationen erhalten bleiben**, was bedeutet, dass Ihr Editor Ihnen weiterhin **automatische Vervollständigung**, **Inline-Fehler**, usw. bieten kann. Das Gleiche gilt für andere Tools wie `mypy`.
@@ -255,8 +321,11 @@ Und Sie können Abhängigkeiten mit `async def` innerhalb normaler `def`-*Pfadop
Es spielt keine Rolle. **FastAPI** weiß, was zu tun ist.
!!! note "Hinweis"
Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-eile){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation.
/// note | "Hinweis"
Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-eile){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation.
///
## Integriert in OpenAPI
@@ -10,41 +10,57 @@ Diese können so **tief** verschachtelt sein, wie nötig.
Sie könnten eine erste Abhängigkeit („Dependable“) wie folgt erstellen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
```Python hl_lines="9-10"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
////
=== "Python 3.10 nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="9-10"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
=== "Python 3.8 nicht annotiert"
//// tab | Python 3.10 nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
////
Diese deklariert einen optionalen Abfrageparameter `q` vom Typ `str` und gibt ihn dann einfach zurück.
@@ -54,41 +70,57 @@ Das ist recht einfach (nicht sehr nützlich), hilft uns aber dabei, uns auf die
Dann können Sie eine weitere Abhängigkeitsfunktion (ein „Dependable“) erstellen, die gleichzeitig eine eigene Abhängigkeit deklariert (also auch ein „Dependant“ ist):
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
```Python hl_lines="14"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
////
=== "Python 3.10 nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="14"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
=== "Python 3.8 nicht annotiert"
//// tab | Python 3.10 nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
////
Betrachten wir die deklarierten Parameter:
@@ -101,46 +133,65 @@ Betrachten wir die deklarierten Parameter:
Diese Abhängigkeit verwenden wir nun wie folgt:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
```Python hl_lines="24"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
////
=== "Python 3.10 nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="24"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
=== "Python 3.8 nicht annotiert"
//// tab | Python 3.10 nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! info
Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`.
///
Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
////
//// tab | Python 3.8 nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
////
/// info
Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`.
Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird.
///
```mermaid
graph TB
@@ -161,22 +212,29 @@ Und es speichert den zurückgegebenen Wert in einem <abbr title="Mechanismus, de
In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in derselben Anfrage aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden:
=== "Python 3.8+"
//// tab | Python 3.8+
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
return {"fresh_value": fresh_value}
```
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
return {"fresh_value": fresh_value}
```
=== "Python 3.8+ nicht annotiert"
////
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
//// tab | Python 3.8+ nicht annotiert
```Python hl_lines="1"
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {"fresh_value": fresh_value}
```
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {"fresh_value": fresh_value}
```
////
## Zusammenfassung
@@ -186,9 +244,12 @@ Einfach Funktionen, die genauso aussehen wie *Pfadoperation-Funktionen*.
Dennoch ist es sehr mächtig und ermöglicht Ihnen die Deklaration beliebig tief verschachtelter Abhängigkeits-„Graphen“ (Bäume).
!!! tip "Tipp"
All dies scheint angesichts dieser einfachen Beispiele möglicherweise nicht so nützlich zu sein.
/// tip | "Tipp"
Aber Sie werden in den Kapiteln über **Sicherheit** sehen, wie nützlich das ist.
All dies scheint angesichts dieser einfachen Beispiele möglicherweise nicht so nützlich zu sein.
Und Sie werden auch sehen, wie viel Code Sie dadurch einsparen.
Aber Sie werden in den Kapiteln über **Sicherheit** sehen, wie nützlich das ist.
Und Sie werden auch sehen, wie viel Code Sie dadurch einsparen.
///
+17 -10
View File
@@ -20,17 +20,21 @@ Sie können für diese Fälle `jsonable_encoder` verwenden.
Es nimmt ein Objekt entgegen, wie etwa ein Pydantic-Modell, und gibt eine JSON-kompatible Version zurück:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="5 22"
{!> ../../../docs_src/encoder/tutorial001.py!}
```
//// tab | Python 3.8+
```Python hl_lines="5 22"
{!> ../../../docs_src/encoder/tutorial001.py!}
```
////
In diesem Beispiel wird das Pydantic-Modell in ein `dict`, und das `datetime`-Objekt in ein `str` konvertiert.
@@ -38,5 +42,8 @@ Das Resultat dieses Aufrufs ist etwas, das mit Pythons Standard-<a href="https:/
Es wird also kein großer `str` zurückgegeben, der die Daten im JSON-Format (als String) enthält. Es wird eine Python-Standarddatenstruktur (z. B. ein `dict`) zurückgegeben, mit Werten und Unterwerten, die alle mit JSON kompatibel sind.
!!! note "Hinweis"
`jsonable_encoder` wird tatsächlich von **FastAPI** intern verwendet, um Daten zu konvertieren. Aber es ist in vielen anderen Szenarien hilfreich.
/// note | "Hinweis"
`jsonable_encoder` wird tatsächlich von **FastAPI** intern verwendet, um Daten zu konvertieren. Aber es ist in vielen anderen Szenarien hilfreich.
///
+80 -48
View File
@@ -55,76 +55,108 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können:
Hier ist ein Beispiel für eine *Pfadoperation* mit Parametern, die einige der oben genannten Typen verwenden.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
```Python hl_lines="1 3 13-17"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="1 3 13-17"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
```Python hl_lines="1 2 11-15"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip
```Python hl_lines="1 2 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1 2 11-15"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1 2 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
////
Beachten Sie, dass die Parameter innerhalb der Funktion ihren natürlichen Datentyp haben und Sie beispielsweise normale Datumsmanipulationen durchführen können, wie zum Beispiel:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
```Python hl_lines="19-20"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="19-20"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
```Python hl_lines="17-18"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17-18"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
////
+82 -50
View File
@@ -8,31 +8,41 @@ Insbesondere Benutzermodelle, denn:
* Das **herausgehende Modell** sollte kein Passwort haben.
* Das **Datenbankmodell** sollte wahrscheinlich ein <abbr title='Ein aus scheinbar zufälligen Zeichen bestehender „Fingerabdruck“ eines Textes. Der Inhalt des Textes kann nicht eingesehen werden.'>gehashtes</abbr> Passwort haben.
!!! danger "Gefahr"
Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können.
/// danger | "Gefahr"
Falls Ihnen das nichts sagt, in den [Sicherheits-Kapiteln](security/simple-oauth2.md#passwort-hashing){.internal-link target=_blank} werden Sie lernen, was ein „Passwort-Hash“ ist.
Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können.
Falls Ihnen das nichts sagt, in den [Sicherheits-Kapiteln](security/simple-oauth2.md#passwort-hashing){.internal-link target=_blank} werden Sie lernen, was ein „Passwort-Hash“ ist.
///
## Mehrere Modelle
Hier der generelle Weg, wie die Modelle mit ihren Passwort-Feldern aussehen könnten, und an welchen Orten sie verwendet werden würden.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
```
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!> ../../../docs_src/extra_models/tutorial001.py!}
```
//// tab | Python 3.8+
!!! info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!> ../../../docs_src/extra_models/tutorial001.py!}
```
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
////
/// info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
///
### Über `**user_in.dict()`
@@ -144,8 +154,11 @@ UserInDB(
)
```
!!! warning "Achtung"
Die Hilfsfunktionen `fake_password_hasher` und `fake_save_user` demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit.
/// warning | "Achtung"
Die Hilfsfunktionen `fake_password_hasher` und `fake_save_user` demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit.
///
## Verdopplung vermeiden
@@ -163,17 +176,21 @@ Die ganze Datenkonvertierung, -validierung, -dokumentation, usw. wird immer noch
Auf diese Weise beschreiben wir nur noch die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password`, und ohne Passwort):
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7 13-14 17-18 21-22"
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
```
```Python hl_lines="7 13-14 17-18 21-22"
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9 15-16 19-20 23-24"
{!> ../../../docs_src/extra_models/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9 15-16 19-20 23-24"
{!> ../../../docs_src/extra_models/tutorial002.py!}
```
////
## `Union`, oder `anyOf`
@@ -183,20 +200,27 @@ Das wird in OpenAPI mit `anyOf` angezeigt.
Um das zu tun, verwenden Sie Pythons Standard-Typhinweis <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>:
!!! note "Hinweis"
Listen Sie, wenn Sie eine <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a> definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in `Union[PlaneItem, CarItem]` also den spezifischeren `PlaneItem` vor dem weniger spezifischen `CarItem`.
/// note | "Hinweis"
=== "Python 3.10+"
Listen Sie, wenn Sie eine <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a> definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in `Union[PlaneItem, CarItem]` also den spezifischeren `PlaneItem` vor dem weniger spezifischen `CarItem`.
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
```
///
=== "Python 3.8+"
//// tab | Python 3.10+
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003.py!}
```
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003.py!}
```
////
### `Union` in Python 3.10
@@ -218,17 +242,21 @@ Genauso können Sie eine Response deklarieren, die eine Liste von Objekten ist.
Verwenden Sie dafür Pythons Standard `typing.List` (oder nur `list` in Python 3.9 und darüber):
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="18"
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
```
```Python hl_lines="18"
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1 20"
{!> ../../../docs_src/extra_models/tutorial004.py!}
```
//// tab | Python 3.8+
```Python hl_lines="1 20"
{!> ../../../docs_src/extra_models/tutorial004.py!}
```
////
## Response mit beliebigem `dict`
@@ -238,17 +266,21 @@ Das ist nützlich, wenn Sie die gültigen Feld-/Attribut-Namen von vorneherein n
In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und darüber):
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="6"
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
```
```Python hl_lines="6"
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1 8"
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
//// tab | Python 3.8+
```Python hl_lines="1 8"
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
////
## Zusammenfassung
+41 -23
View File
@@ -24,12 +24,15 @@ $ uvicorn main:app --reload
</div>
!!! note "Hinweis"
Der Befehl `uvicorn main:app` bezieht sich auf:
/// note | "Hinweis"
* `main`: die Datei `main.py` (das sogenannte Python-„Modul“).
* `app`: das Objekt, welches in der Datei `main.py` mit der Zeile `app = FastAPI()` erzeugt wurde.
* `--reload`: lässt den Server nach Codeänderungen neu starten. Verwenden Sie das nur während der Entwicklung.
Der Befehl `uvicorn main:app` bezieht sich auf:
* `main`: die Datei `main.py` (das sogenannte Python-„Modul“).
* `app`: das Objekt, welches in der Datei `main.py` mit der Zeile `app = FastAPI()` erzeugt wurde.
* `--reload`: lässt den Server nach Codeänderungen neu starten. Verwenden Sie das nur während der Entwicklung.
///
In der Konsolenausgabe sollte es eine Zeile geben, die ungefähr so aussieht:
@@ -136,10 +139,13 @@ Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generier
`FastAPI` ist eine Python-Klasse, die die gesamte Funktionalität für Ihre API bereitstellt.
!!! note "Technische Details"
`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt.
/// note | "Technische Details"
Sie können alle <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>-Funktionalitäten auch mit `FastAPI` nutzen.
`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt.
Sie können alle <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>-Funktionalitäten auch mit `FastAPI` nutzen.
///
### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“
@@ -199,8 +205,11 @@ https://example.com/items/foo
/items/foo
```
!!! info
Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet.
/// info
Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet.
///
Bei der Erstellung einer API ist der „Pfad“ die wichtigste Möglichkeit zur Trennung von „Anliegen“ und „Ressourcen“.
@@ -250,16 +259,19 @@ Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die
* den Pfad `/`
* unter der Verwendung der <abbr title="eine HTTP GET Methode"><code>get</code>-Operation</abbr> gehen
!!! info "`@decorator` Information"
Diese `@something`-Syntax wird in Python „Dekorator“ genannt.
/// info | "`@decorator` Information"
Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff).
Diese `@something`-Syntax wird in Python „Dekorator“ genannt.
Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit.
Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff).
In unserem Fall teilt dieser Dekorator **FastAPI** mit, dass die folgende Funktion mit dem **Pfad** `/` und der **Operation** `get` zusammenhängt.
Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit.
Dies ist der „**Pfadoperation-Dekorator**“.
In unserem Fall teilt dieser Dekorator **FastAPI** mit, dass die folgende Funktion mit dem **Pfad** `/` und der **Operation** `get` zusammenhängt.
Dies ist der „**Pfadoperation-Dekorator**“.
///
Sie können auch die anderen Operationen verwenden:
@@ -274,14 +286,17 @@ Oder die exotischeren:
* `@app.patch()`
* `@app.trace()`
!!! tip "Tipp"
Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten.
/// tip | "Tipp"
**FastAPI** erzwingt keine bestimmte Bedeutung.
Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten.
Die hier aufgeführten Informationen dienen als Leitfaden und sind nicht verbindlich.
**FastAPI** erzwingt keine bestimmte Bedeutung.
Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktionen nur mit „POST“-Operationen durch.
Die hier aufgeführten Informationen dienen als Leitfaden und sind nicht verbindlich.
Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktionen nur mit „POST“-Operationen durch.
///
### Schritt 4: Definieren der **Pfadoperation-Funktion**
@@ -309,8 +324,11 @@ Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note "Hinweis"
Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-eile){.internal-link target=_blank}.
/// note | "Hinweis"
Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-eile){.internal-link target=_blank}.
///
### Schritt 5: den Inhalt zurückgeben
+24 -12
View File
@@ -63,12 +63,15 @@ Aber wenn der Client `http://example.com/items/bar` anfragt (ein nicht-existiere
}
```
!!! tip "Tipp"
Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der nach JSON konvertiert werden kann, nicht nur `str`.
/// tip | "Tipp"
Zum Beispiel ein `dict`, eine `list`, usw.
Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der nach JSON konvertiert werden kann, nicht nur `str`.
Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert.
Zum Beispiel ein `dict`, eine `list`, usw.
Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert.
///
## Benutzerdefinierte Header hinzufügen
@@ -106,10 +109,13 @@ Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-I
{"message": "Oops! yolo did something. There goes a rainbow..."}
```
!!! note "Technische Details"
Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden.
/// note | "Technische Details"
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `Request`.
Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `Request`.
///
## Die Default-Exceptionhandler überschreiben
@@ -160,8 +166,11 @@ path -> item_id
#### `RequestValidationError` vs. `ValidationError`
!!! warning "Achtung"
Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind.
/// warning | "Achtung"
Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind.
///
`RequestValidationError` ist eine Unterklasse von Pydantics <a href="https://pydantic-docs.helpmanual.io/usage/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
@@ -183,10 +192,13 @@ Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zu
{!../../../docs_src/handling_errors/tutorial004.py!}
```
!!! note "Technische Details"
Sie können auch `from starlette.responses import PlainTextResponse` verwenden.
/// note | "Technische Details"
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
Sie können auch `from starlette.responses import PlainTextResponse` verwenden.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
///
### Den `RequestValidationError`-Body verwenden
+187 -109
View File
@@ -6,41 +6,57 @@ So wie `Query`-, `Path`-, und `Cookie`-Parameter können Sie auch <abbr title='H
Importieren Sie zuerst `Header`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
////
## `Header`-Parameter deklarieren
@@ -48,49 +64,71 @@ Dann deklarieren Sie Ihre Header-Parameter, auf die gleiche Weise, wie Sie auch
Der erste Wert ist der Typ. Sie können `Header` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! note "Technische Details"
`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
///
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Header` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
!!! info
Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
////
/// note | "Technische Details"
`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Header` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
///
/// info
Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
///
## Automatische Konvertierung
@@ -108,44 +146,63 @@ Sie können also `user_agent` schreiben, wie Sie es normalerweise in Python-Code
Wenn Sie aus irgendeinem Grund das automatische Konvertieren von Unterstrichen zu Bindestrichen abschalten möchten, setzen Sie den Parameter `convert_underscores` auf `False`.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="11"
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="11"
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/header_params/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="12"
{!> ../../../docs_src/header_params/tutorial002_an.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! warning "Achtung"
Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HTTP-Proxys und Server die Verwendung von Headern mit Unterstrichen nicht erlauben.
///
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002.py!}
```
////
/// warning | "Achtung"
Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HTTP-Proxys und Server die Verwendung von Headern mit Unterstrichen nicht erlauben.
///
## Doppelte Header
@@ -157,50 +214,71 @@ Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`e.
Um zum Beispiel einen Header `X-Token` zu deklarieren, der mehrmals vorkommen kann, schreiben Sie:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial003_an.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
```
////
=== "Python 3.9+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
=== "Python 3.8+ nicht annotiert"
///
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003.py!}
```
////
//// tab | Python 3.9+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003.py!}
```
////
Wenn Sie mit einer *Pfadoperation* kommunizieren, die zwei HTTP-Header sendet, wie:
+14 -11
View File
@@ -52,22 +52,25 @@ $ pip install "fastapi[all]"
... das beinhaltet auch `uvicorn`, welchen Sie als Server verwenden können, der ihren Code ausführt.
!!! note "Hinweis"
Sie können die einzelnen Teile auch separat installieren.
/// note | "Hinweis"
Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen:
Sie können die einzelnen Teile auch separat installieren.
```
pip install fastapi
```
Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen:
Installieren Sie auch `uvicorn` als Server:
```
pip install fastapi
```
```
pip install "uvicorn[standard]"
```
Installieren Sie auch `uvicorn` als Server:
Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten.
```
pip install "uvicorn[standard]"
```
Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten.
///
## Handbuch für fortgeschrittene Benutzer
+15 -6
View File
@@ -22,8 +22,11 @@ Sie können diese wie folgt setzen:
{!../../../docs_src/metadata/tutorial001.py!}
```
!!! tip "Tipp"
Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert.
/// tip | "Tipp"
Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert.
///
Mit dieser Konfiguration würde die automatische API-Dokumentation wie folgt aussehen:
@@ -65,8 +68,11 @@ Erstellen Sie Metadaten für Ihre Tags und übergeben Sie sie an den Parameter `
Beachten Sie, dass Sie Markdown in den Beschreibungen verwenden können. Beispielsweise wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
!!! tip "Tipp"
Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
/// tip | "Tipp"
Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
///
### Ihre Tags verwenden
@@ -76,8 +82,11 @@ Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n
{!../../../docs_src/metadata/tutorial004.py!}
```
!!! info
Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}.
/// info
Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}.
///
### Die Dokumentation anschauen
+18 -9
View File
@@ -11,10 +11,13 @@ Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bev
* Sie kann etwas mit dieser **Response** tun oder beliebigen Code ausführen.
* Dann gibt sie die **Response** zurück.
!!! note "Technische Details"
Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt.
/// note | "Technische Details"
Wenn es Hintergrundaufgaben gab (später dokumentiert), werden sie *nach* allen Middlewares ausgeführt.
Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt.
Wenn es Hintergrundaufgaben gab (später dokumentiert), werden sie *nach* allen Middlewares ausgeführt.
///
## Erstellung einer Middleware
@@ -32,15 +35,21 @@ Die Middleware-Funktion erhält:
{!../../../docs_src/middleware/tutorial001.py!}
```
!!! tip "Tipp"
Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">Verwenden Sie dafür das Präfix 'X-'</a>.
/// tip | "Tipp"
Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfigurationen ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette-CORS-Dokumentation</a> dokumentiert ist.
Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">Verwenden Sie dafür das Präfix 'X-'</a>.
!!! note "Technische Details"
Sie könnten auch `from starlette.requests import Request` verwenden.
Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfigurationen ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette-CORS-Dokumentation</a> dokumentiert ist.
**FastAPI** bietet es als Komfort für Sie, den Entwickler, an. Aber es stammt direkt von Starlette.
///
/// note | "Technische Details"
Sie könnten auch `from starlette.requests import Request` verwenden.
**FastAPI** bietet es als Komfort für Sie, den Entwickler, an. Aber es stammt direkt von Starlette.
///
### Vor und nach der `response`
@@ -2,8 +2,11 @@
Es gibt mehrere Konfigurations-Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können.
!!! warning "Achtung"
Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeben werden, nicht der *Pfadoperation-Funktion*.
/// warning | "Achtung"
Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeben werden, nicht der *Pfadoperation-Funktion*.
///
## Response-Statuscode
@@ -13,52 +16,67 @@ Sie können direkt den `int`-Code übergeben, etwa `404`.
Aber falls Sie sich nicht mehr erinnern, wofür jede Nummer steht, können Sie die Abkürzungs-Konstanten in `status` verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="1 15"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```
```Python hl_lines="1 15"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
```
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```
////
Dieser Statuscode wird in der Response verwendet und zum OpenAPI-Schema hinzugefügt.
!!! note "Technische Details"
Sie können auch `from starlette import status` verwenden.
/// note | "Technische Details"
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
Sie können auch `from starlette import status` verwenden.
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
///
## Tags
Sie können Ihrer *Pfadoperation* Tags hinzufügen, mittels des Parameters `tags`, dem eine `list`e von `str`s übergeben wird (in der Regel nur ein `str`):
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="15 20 25"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```
```Python hl_lines="15 20 25"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
```
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```
////
Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumentations-Benutzeroberflächen verwendet:
@@ -80,23 +98,29 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern.
Sie können eine Zusammenfassung (`summary`) und eine Beschreibung (`description`) hinzufügen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="18-19"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```
```Python hl_lines="18-19"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
```
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```
////
## Beschreibung mittels Docstring
@@ -104,23 +128,29 @@ Da Beschreibungen oft mehrere Zeilen lang sind, können Sie die Beschreibung der
Sie können im Docstring <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> schreiben, es wird korrekt interpretiert und angezeigt (die Einrückung des Docstring beachtend).
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="17-25"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```
```Python hl_lines="17-25"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
```
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```
////
In der interaktiven Dokumentation sieht das dann so aus:
@@ -130,31 +160,43 @@ In der interaktiven Dokumentation sieht das dann so aus:
Die Response können Sie mit dem Parameter `response_description` beschreiben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```
```Python hl_lines="19"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
```
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```
////
!!! info
beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
//// tab | Python 3.8+
!!! check
OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt.
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```
Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolgreiche Response“ erstellen.
////
/// info
beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
///
/// check
OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt.
Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolgreiche Response“ erstellen.
///
<img src="/img/tutorial/path-operation-configuration/image03.png">
@@ -6,48 +6,67 @@ So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metad
Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
```Python hl_lines="3-4"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="3-4"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
```Python hl_lines="1"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! info
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
///
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
```Python hl_lines="1"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
////
/// info
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
///
## Metadaten deklarieren
@@ -55,53 +74,75 @@ Sie können die gleichen Parameter deklarieren wie für `Query`.
Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, schreiben Sie:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! note "Hinweis"
Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss.
///
Sie sollten ihn daher mit `...` deklarieren, um ihn als erforderlich auszuzeichnen.
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
Doch selbst wenn Sie ihn mit `None` deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich.
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
////
/// note | "Hinweis"
Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss.
Sie sollten ihn daher mit `...` deklarieren, um ihn als erforderlich auszuzeichnen.
Doch selbst wenn Sie ihn mit `None` deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich.
///
## Sortieren Sie die Parameter, wie Sie möchten
!!! tip "Tipp"
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
/// tip | "Tipp"
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
///
Nehmen wir an, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren.
@@ -117,33 +158,45 @@ Für **FastAPI** ist es nicht wichtig. Es erkennt die Parameter anhand ihres Nam
Sie können Ihre Funktion also so deklarieren:
=== "Python 3.8 nicht annotiert"
//// tab | Python 3.8 nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="7"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
////
Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da Sie nicht die Funktions-Parameter-Defaultwerte für `Query()` oder `Path()` verwenden.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
```
////
## Sortieren Sie die Parameter wie Sie möchten: Tricks
!!! tip "Tipp"
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
/// tip | "Tipp"
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
///
Hier ein **kleiner Trick**, der nützlich sein kann, aber Sie werden ihn nicht oft brauchen.
@@ -168,43 +221,56 @@ Python macht nichts mit diesem `*`, aber es wird wissen, dass alle folgenden Par
Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, dieses Problem nicht haben, weil Sie keine Defaultwerte für Ihre Funktionsparameter haben. Sie müssen daher wahrscheinlich auch nicht `*` verwenden.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
```
////
## Validierung von Zahlen: Größer oder gleich
Mit `Query` und `Path` (und anderen, die Sie später kennenlernen), können Sie Zahlenbeschränkungen deklarieren.
Hier, mit `ge=1`, wird festgelegt, dass `item_id` eine Ganzzahl benötigt, die größer oder gleich `1` ist (`g`reater than or `e`qual).
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
////
## Validierung von Zahlen: Größer und kleiner oder gleich
@@ -213,26 +279,35 @@ Das Gleiche trifft zu auf:
* `gt`: `g`reater `t`han – größer als
* `le`: `l`ess than or `e`qual – kleiner oder gleich
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
```
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
////
## Validierung von Zahlen: Floats, größer und kleiner
@@ -244,26 +319,35 @@ Hier wird es wichtig, in der Lage zu sein, <abbr title="greater than – größe
Das gleiche gilt für <abbr title="less than – kleiner als"><code>lt</code></abbr>.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="13"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
```
```Python hl_lines="13"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="12"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="12"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
```
////
## Zusammenfassung
@@ -276,18 +360,24 @@ Und Sie können auch Validierungen für Zahlen deklarieren:
* `lt`: `l`ess `t`han – kleiner als
* `le`: `l`ess than or `e`qual – kleiner oder gleich
!!! info
`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse.
/// info
Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse.
!!! note "Technische Details"
`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen.
Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.
///
Sie importieren also `Query`, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch `Query` genannt wird.
/// note | "Technische Details"
Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt.
`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen.
Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.
Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.
Sie importieren also `Query`, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch `Query` genannt wird.
Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt.
Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.
///
+45 -21
View File
@@ -24,8 +24,11 @@ Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion dekl
In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl.
!!! check
Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw.
/// check
Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw.
///
## Daten-<abbr title="Auch bekannt als: Serialisierung, Parsen, Marshalling">Konversion</abbr>
@@ -35,10 +38,13 @@ Wenn Sie dieses Beispiel ausführen und Ihren Browser unter <a href="http://127.
{"item_id":3}
```
!!! check
Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String `"3"`, also ein `str`.
/// check
Sprich, mit dieser Typdeklaration wird **FastAPI** die Anfrage automatisch <abbr title="Den String, der von einer HTTP Anfrage kommt, in Python-Objekte konvertieren">„parsen“</abbr>.
Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String `"3"`, also ein `str`.
Sprich, mit dieser Typdeklaration wird **FastAPI** die Anfrage automatisch <abbr title="Den String, der von einer HTTP Anfrage kommt, in Python-Objekte konvertieren">„parsen“</abbr>.
///
## Datenvalidierung
@@ -65,12 +71,15 @@ Der Pfad-Parameter `item_id` hatte den Wert `"foo"`, was kein `int` ist.
Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein `float` (also eine Kommazahl) statt eines `int`s übergeben würden, wie etwa in: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
!!! check
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung.
/// check
Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war.
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung.
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert.
Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war.
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert.
///
## Dokumentation
@@ -78,10 +87,13 @@ Wenn Sie die Seite <a href="http://127.0.0.1:8000/docs" class="external-link" ta
<img src="/img/tutorial/path-params/image01.png">
!!! check
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
/// check
Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
///
## Nützliche Standards. Alternative Dokumentation
@@ -141,11 +153,17 @@ Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaub
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder kurz Enums)</a> gibt es in Python seit Version 3.4.
/// info
!!! tip "Tipp"
Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das sind Namen von <abbr title="Genau genommen, Deep-Learning-Modellarchitekturen">Modellen</abbr> für maschinelles Lernen.
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder kurz Enums)</a> gibt es in Python seit Version 3.4.
///
/// tip | "Tipp"
Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das sind Namen von <abbr title="Genau genommen, Deep-Learning-Modellarchitekturen">Modellen</abbr> für maschinelles Lernen.
///
### Deklarieren Sie einen *Pfad-Parameter*
@@ -181,8 +199,11 @@ Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip "Tipp"
Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen.
/// tip | "Tipp"
Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen.
///
#### *Enum-Member* zurückgeben
@@ -235,10 +256,13 @@ Sie verwenden das also wie folgt:
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip "Tipp"
Der Parameter könnte einen führenden Schrägstrich (`/`) haben, wie etwa in `/home/johndoe/myfile.txt`.
/// tip | "Tipp"
In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelten Schrägstrich (`//`) zwischen `files` und `home`.
Der Parameter könnte einen führenden Schrägstrich (`/`) haben, wie etwa in `/home/johndoe/myfile.txt`.
In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelten Schrägstrich (`//`) zwischen `files` und `home`.
///
## Zusammenfassung
File diff suppressed because it is too large. Load diff
+58 -36
View File
@@ -63,38 +63,49 @@ gehen, werden die Parameter-Werte Ihrer Funktion sein:
Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem Sie deren Defaultwert auf `None` setzen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
////
In diesem Fall wird der Funktionsparameter `q` optional, und standardmäßig `None` sein.
!!! check
Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein.
/// check
Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein.
///
## Query-Parameter Typkonvertierung
Sie können auch `bool`-Typen deklarieren und sie werden konvertiert:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
////
Wenn Sie nun zu:
@@ -136,17 +147,21 @@ Und Sie müssen sie auch nicht in einer spezifischen Reihenfolge deklarieren.
Parameter werden anhand ihres Namens erkannt:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
//// tab | Python 3.8+
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
////
## Erforderliche Query-Parameter
@@ -204,17 +219,21 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
Und natürlich können Sie einige Parameter als erforderlich, einige mit Defaultwert, und einige als vollständig optional definieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
//// tab | Python 3.8+
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
////
In diesem Fall gibt es drei Query-Parameter:
@@ -222,5 +241,8 @@ In diesem Fall gibt es drei Query-Parameter:
* `skip`, ein `int` mit einem Defaultwert `0`.
* `limit`, ein optionales `int`.
!!! tip "Tipp"
Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#vordefinierte-parameterwerte){.internal-link target=_blank}.
/// tip | "Tipp"
Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#vordefinierte-parameterwerte){.internal-link target=_blank}.
///
+247 -143
View File
@@ -2,70 +2,97 @@
Mit `File` können sie vom Client hochzuladende Dateien definieren.
!!! info
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
/// info
Z. B. `pip install python-multipart`.
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden.
Z. B. `pip install python-multipart`.
Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden.
///
## `File` importieren
Importieren Sie `File` und `UploadFile` von `fastapi`:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="3"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
////
## `File`-Parameter definieren
Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="9"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="8"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="8"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="7"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
!!! info
`File` ist eine Klasse, die direkt von `Form` erbt.
/// tip | "Tipp"
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! tip "Tipp"
Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
///
```Python hl_lines="7"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
////
/// info
`File` ist eine Klasse, die direkt von `Form` erbt.
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben
///
/// tip | "Tipp"
Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
///
Die Dateien werden als „Formulardaten“ hochgeladen.
@@ -79,26 +106,35 @@ Aber es gibt viele Fälle, in denen Sie davon profitieren, `UploadFile` zu verwe
Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="14"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
```Python hl_lines="14"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="13"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="13"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="12"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="12"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
////
`UploadFile` zu verwenden, hat mehrere Vorzüge gegenüber `bytes`:
@@ -141,11 +177,17 @@ Wenn Sie sich innerhalb einer normalen `def`-*Pfadoperation-Funktion* befinden,
contents = myfile.file.read()
```
!!! note "Technische Details zu `async`"
Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden in einem <abbr title="Mehrere unabhängige Kindprozesse">Threadpool</abbr> aus und erwartet sie.
/// note | "Technische Details zu `async`"
!!! note "Technische Details zu Starlette"
**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen.
Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden in einem <abbr title="Mehrere unabhängige Kindprozesse">Threadpool</abbr> aus und erwartet sie.
///
/// note | "Technische Details zu Starlette"
**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen.
///
## Was sind „Formulardaten“
@@ -153,82 +195,113 @@ HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodi
**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
!!! note "Technische Details"
Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
/// note | "Technische Details"
Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss.
Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss.
!!! warning "Achtung"
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
/// warning | "Achtung"
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Optionaler Datei-Upload
Sie können eine Datei optional machen, indem Sie Standard-Typannotationen verwenden und den Defaultwert auf `None` setzen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
```
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
```
```Python hl_lines="10 18"
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10 18"
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
```
```Python hl_lines="7 15"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7 15"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
////
## `UploadFile` mit zusätzlichen Metadaten
Sie können auch `File()` zusammen mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="9 15"
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
```
```Python hl_lines="9 15"
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="8 14"
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="8 14"
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="7 13"
{!> ../../../docs_src/request_files/tutorial001_03.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7 13"
{!> ../../../docs_src/request_files/tutorial001_03.py!}
```
////
## Mehrere Datei-Uploads
@@ -238,76 +311,107 @@ Diese werden demselben Formularfeld zugeordnet, welches mit den Formulardaten ge
Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
```
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="11 16"
{!> ../../../docs_src/request_files/tutorial002_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.9+ nicht annotiert"
```Python hl_lines="11 16"
{!> ../../../docs_src/request_files/tutorial002_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
//// tab | Python 3.9+ nicht annotiert
=== "Python 3.8+ nicht annotiert"
/// tip | "Tipp"
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
///
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
////
Sie erhalten, wie deklariert, eine `list`e von `bytes` oder `UploadFile`s.
!!! note "Technische Details"
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
/// note | "Technische Details"
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
///
### Mehrere Datei-Uploads mit zusätzlichen Metadaten
Und so wie zuvor können Sie `File()` verwenden, um zusätzliche Parameter zu setzen, sogar für `UploadFile`:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="11 18-20"
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
```
```Python hl_lines="11 18-20"
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="12 19-21"
{!> ../../../docs_src/request_files/tutorial003_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.9+ nicht annotiert"
```Python hl_lines="12 19-21"
{!> ../../../docs_src/request_files/tutorial003_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="9 16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
//// tab | Python 3.9+ nicht annotiert
=== "Python 3.8+ nicht annotiert"
/// tip | "Tipp"
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="11 18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
///
```Python hl_lines="9 16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="11 18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
////
## Zusammenfassung
@@ -2,67 +2,91 @@
Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren.
!!! info
Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
/// info
Z. B. `pip install python-multipart`.
Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
Z. B. `pip install python-multipart`.
///
## `File` und `Form` importieren
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="3"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
////
## `File` und `Form`-Parameter definieren
Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` und `Query` machen würden:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="10-12"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
```Python hl_lines="10-12"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9-11"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="9-11"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="8"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="8"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
////
Die Datei- und Formularfelder werden als Formulardaten hochgeladen, und Sie erhalten diese Dateien und Formularfelder.
Und Sie können einige der Dateien als `bytes` und einige als `UploadFile` deklarieren.
!!! warning "Achtung"
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
/// warning | "Achtung"
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Zusammenfassung
+75 -42
View File
@@ -2,60 +2,81 @@
Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden.
!!! info
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
/// info
Z. B. `pip install python-multipart`.
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
Z. B. `pip install python-multipart`.
///
## `Form` importieren
Importieren Sie `Form` von `fastapi`:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="3"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
```Python hl_lines="3"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
////
## `Form`-Parameter definieren
Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen würden:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="9"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
```Python hl_lines="9"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="8"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="8"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="7"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
////
Zum Beispiel stellt eine der Möglichkeiten, die OAuth2 Spezifikation zu verwenden (genannt <abbr title='„Passwort-Fluss“'>„password flow“</abbr>), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden.
@@ -63,11 +84,17 @@ Die <abbr title="Specification – Spezifikation">Spec</abbr> erfordert, dass di
Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw.
!!! info
`Form` ist eine Klasse, die direkt von `Body` erbt.
/// info
!!! tip "Tipp"
Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
`Form` ist eine Klasse, die direkt von `Body` erbt.
///
/// tip | "Tipp"
Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
///
## Über „Formularfelder“
@@ -75,17 +102,23 @@ HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodi
**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
!!! note "Technische Details"
Daten aus Formularen werden normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
/// note | "Technische Details"
Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien.
Daten aus Formularen werden normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien.
!!! warning "Achtung"
Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert.
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
/// warning | "Achtung"
Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Zusammenfassung
+253 -159
View File
@@ -4,23 +4,29 @@ Sie können den Typ der <abbr title="Response – Antwort: Daten, die zum anfrag
Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten von Funktions-**Parametern** machen; verwenden Sie Pydantic-Modelle, Listen, Dicts und skalare Werte wie Nummern, Booleans, usw.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="16 21"
{!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
```
```Python hl_lines="16 21"
{!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
```
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01.py!}
```
////
FastAPI wird diesen Rückgabetyp verwenden, um:
@@ -53,35 +59,47 @@ Sie können `response_model` in jeder möglichen *Pfadoperation* verwenden:
* `@app.delete()`
* usw.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
```
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
```
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001.py!}
```
////
!!! note "Hinweis"
Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter.
//// tab | Python 3.8+
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001.py!}
```
////
/// note | "Hinweis"
Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter.
///
`response_model` nimmt denselben Typ entgegen, den Sie auch für ein Pydantic-Modellfeld deklarieren würden, also etwa ein Pydantic-Modell, aber es kann auch z. B. eine `list`e von Pydantic-Modellen sein, wie etwa `List[Item]`.
FastAPI wird dieses `response_model` nehmen, um die Daten zu dokumentieren, validieren, usw. und auch, um **die Ausgabedaten** entsprechend der Typdeklaration **zu konvertieren und filtern**.
!!! tip "Tipp"
Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als <abbr title='„Irgend etwas“'>`Any`</abbr> deklarieren.
/// tip | "Tipp"
So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`.
Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als <abbr title='„Irgend etwas“'>`Any`</abbr> deklarieren.
So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`.
///
### `response_model`-Priorität
@@ -95,37 +113,48 @@ Sie können auch `response_model=None` verwenden, um das Erstellen eines Respons
Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passwort:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7 9"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
```Python hl_lines="7 9"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9 11"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
//// tab | Python 3.8+
!!! info
Um `EmailStr` zu verwenden, installieren Sie zuerst <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
```Python hl_lines="9 11"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
Z. B. `pip install email-validator`
oder `pip install pydantic[email]`.
////
/// info
Um `EmailStr` zu verwenden, installieren Sie zuerst <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
Z. B. `pip install email-validator`
oder `pip install pydantic[email]`.
///
Wir verwenden dieses Modell, um sowohl unsere Eingabe- als auch Ausgabedaten zu deklarieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
```Python hl_lines="16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="18"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="18"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
////
Immer wenn jetzt ein Browser einen Benutzer mit Passwort erzeugt, gibt die API dasselbe Passwort in der Response zurück.
@@ -133,52 +162,67 @@ Hier ist das möglicherweise kein Problem, da es derselbe Benutzer ist, der das
Aber wenn wir dasselbe Modell für eine andere *Pfadoperation* verwenden, könnten wir das Passwort dieses Benutzers zu jedem Client schicken.
!!! danger "Gefahr"
Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie es in einer Response wie dieser, wenn Sie sich nicht der resultierenden Gefahren bewusst sind und nicht wissen, was Sie tun.
/// danger | "Gefahr"
Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie es in einer Response wie dieser, wenn Sie sich nicht der resultierenden Gefahren bewusst sind und nicht wissen, was Sie tun.
///
## Ausgabemodell hinzufügen
Wir können stattdessen ein Eingabemodell mit dem Klartext-Passwort, und ein Ausgabemodell ohne das Passwort erstellen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
////
Obwohl unsere *Pfadoperation-Funktion* hier denselben `user` von der Eingabe zurückgibt, der das Passwort enthält:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
//// tab | Python 3.8+
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
////
... haben wir deklariert, dass `response_model` das Modell `UserOut` ist, welches das Passwort nicht enthält:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
//// tab | Python 3.8+
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
////
Darum wird **FastAPI** sich darum kümmern, dass alle Daten, die nicht im Ausgabemodell deklariert sind, herausgefiltert werden (mittels Pydantic).
@@ -202,17 +246,21 @@ Aber in den meisten Fällen, wenn wir so etwas machen, wollen wir nur, dass das
Und in solchen Fällen können wir Klassen und Vererbung verwenden, um Vorteil aus den Typannotationen in der Funktion zu ziehen, was vom Editor und von Tools besser unterstützt wird, während wir gleichzeitig FastAPIs **Datenfilterung** behalten.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7-10 13-14 18"
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
```
```Python hl_lines="7-10 13-14 18"
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9-13 15-16 20"
{!> ../../../docs_src/response_model/tutorial003_01.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9-13 15-16 20"
{!> ../../../docs_src/response_model/tutorial003_01.py!}
```
////
Damit erhalten wir Tool-Unterstützung, vom Editor und mypy, da dieser Code hinsichtlich der Typen korrekt ist, aber wir erhalten auch die Datenfilterung von FastAPI.
@@ -278,17 +326,21 @@ Aber wenn Sie ein beliebiges anderes Objekt zurückgeben, das kein gültiger Pyd
Das gleiche wird passieren, wenn Sie eine <abbr title='Eine Union mehrerer Typen bedeutet: „Irgendeiner dieser Typen“'>Union</abbr> mehrerer Typen haben, und einer oder mehrere sind nicht gültige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht 💥:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="8"
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="10"
{!> ../../../docs_src/response_model/tutorial003_04.py!}
```
//// tab | Python 3.8+
```Python hl_lines="10"
{!> ../../../docs_src/response_model/tutorial003_04.py!}
```
////
... das scheitert, da die Typannotation kein Pydantic-Typ ist, und auch keine einzelne `Response`-Klasse, oder -Unterklasse, es ist eine Union (eines von beiden) von `Response` und `dict`.
@@ -300,17 +352,21 @@ Aber Sie möchten dennoch den Rückgabetyp in der Funktion annotieren, um Unters
In diesem Fall können Sie die Generierung des Responsemodells abschalten, indem Sie `response_model=None` setzen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7"
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
```
```Python hl_lines="7"
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="9"
{!> ../../../docs_src/response_model/tutorial003_05.py!}
```
//// tab | Python 3.8+
```Python hl_lines="9"
{!> ../../../docs_src/response_model/tutorial003_05.py!}
```
////
Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und damit können Sie jede gewünschte Rückgabetyp-Annotation haben, ohne dass es Ihre FastAPI-Anwendung beeinflusst. 🤓
@@ -318,23 +374,29 @@ Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und d
Ihr Responsemodell könnte Defaultwerte haben, wie:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="9 11-12"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
```Python hl_lines="9 11-12"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
////
* `description: Union[str, None] = None` (oder `str | None = None` in Python 3.10) hat einen Defaultwert `None`.
* `tax: float = 10.5` hat einen Defaultwert `10.5`.
@@ -348,23 +410,29 @@ Wenn Sie zum Beispiel Modelle mit vielen optionalen Attributen in einer NoSQL-Da
Sie können den *Pfadoperation-Dekorator*-Parameter `response_model_exclude_unset=True` setzen:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
////
Die Defaultwerte werden dann nicht in der Response enthalten sein, sondern nur die tatsächlich gesetzten Werte.
@@ -377,21 +445,30 @@ Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wir
}
```
!!! info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
/// info
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
!!! info
FastAPI verwendet `.dict()` von Pydantic Modellen, <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">mit dessen `exclude_unset`-Parameter</a>, um das zu erreichen.
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
!!! info
Sie können auch:
///
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
/// info
verwenden, wie in der <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydantic Dokumentation</a> für `exclude_defaults` und `exclude_none` beschrieben.
FastAPI verwendet `.dict()` von Pydantic Modellen, <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">mit dessen `exclude_unset`-Parameter</a>, um das zu erreichen.
///
/// info
Sie können auch:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
verwenden, wie in der <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydantic Dokumentation</a> für `exclude_defaults` und `exclude_none` beschrieben.
///
#### Daten mit Werten für Felder mit Defaultwerten
@@ -426,10 +503,13 @@ dann ist FastAPI klug genug (tatsächlich ist Pydantic klug genug) zu erkennen,
Diese Felder werden also in der JSON-Response enthalten sein.
!!! tip "Tipp"
Beachten Sie, dass Defaultwerte alles Mögliche sein können, nicht nur `None`.
/// tip | "Tipp"
Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein.
Beachten Sie, dass Defaultwerte alles Mögliche sein können, nicht nur `None`.
Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein.
///
### `response_model_include` und `response_model_exclude`
@@ -439,45 +519,59 @@ Diese nehmen ein `set` von `str`s entgegen, welches Namen von Attributen sind, d
Das kann als schnelle Abkürzung verwendet werden, wenn Sie nur ein Pydantic-Modell haben und ein paar Daten von der Ausgabe ausschließen wollen.
!!! tip "Tipp"
Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter.
/// tip | "Tipp"
Der Grund ist, dass das das generierte JSON-Schema in der OpenAPI ihrer Anwendung (und deren Dokumentation) dennoch das komplette Modell abbildet, selbst wenn Sie `response_model_include` oder `response_model_exclude` verwenden, um einige Attribute auszuschließen.
Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter.
Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert.
Der Grund ist, dass das das generierte JSON-Schema in der OpenAPI ihrer Anwendung (und deren Dokumentation) dennoch das komplette Modell abbildet, selbst wenn Sie `response_model_include` oder `response_model_exclude` verwenden, um einige Attribute auszuschließen.
=== "Python 3.10+"
Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert.
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
```
///
=== "Python 3.8+"
//// tab | Python 3.10+
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial005.py!}
```
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
```
!!! tip "Tipp"
Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten.
////
Äquivalent zu `set(["name", "description"])`.
//// tab | Python 3.8+
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial005.py!}
```
////
/// tip | "Tipp"
Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten.
Äquivalent zu `set(["name", "description"])`.
///
#### `list`en statt `set`s verwenden
Wenn Sie vergessen, ein `set` zu verwenden, und stattdessen eine `list`e oder ein `tuple` übergeben, wird FastAPI die dennoch in ein `set` konvertieren, und es wird korrekt funktionieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
```
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial006.py!}
```
//// tab | Python 3.8+
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial006.py!}
```
////
## Zusammenfassung
+32 -14
View File
@@ -12,13 +12,19 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo
{!../../../docs_src/response_status_code/tutorial001.py!}
```
!!! note "Hinweis"
Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body.
/// note | "Hinweis"
Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body.
///
Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben.
!!! info
Alternativ kann `status_code` auch ein `IntEnum` erhalten, so wie Pythons <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
/// info
Alternativ kann `status_code` auch ein `IntEnum` erhalten, so wie Pythons <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
///
Das wird:
@@ -27,15 +33,21 @@ Das wird:
<img src="/img/tutorial/response-status-code/image01.png">
!!! note "Hinweis"
Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat.
/// note | "Hinweis"
FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt.
Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat.
FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt.
///
## Über HTTP-Statuscodes
!!! note "Hinweis"
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
/// note | "Hinweis"
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
///
In HTTP senden Sie als Teil der Response einen aus drei Ziffern bestehenden numerischen Statuscode.
@@ -54,8 +66,11 @@ Kurz:
* Für allgemeine Fehler beim Client können Sie einfach `400` verwenden.
* `500` und darüber stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn etwas an irgendeiner Stelle in Ihrem Anwendungscode oder im Server schiefläuft, wird automatisch einer dieser Fehler-Statuscodes zurückgegeben.
!!! tip "Tipp"
Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr> Dokumentation über HTTP-Statuscodes</a>.
/// tip | "Tipp"
Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr> Dokumentation über HTTP-Statuscodes</a>.
///
## Abkürzung, um die Namen zu erinnern
@@ -79,10 +94,13 @@ Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese
<img src="/img/tutorial/response-status-code/image02.png">
!!! note "Technische Details"
Sie können auch `from starlette import status` verwenden.
/// note | "Technische Details"
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
Sie können auch `from starlette import status` verwenden.
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
///
## Den Defaultwert ändern
+203 -121
View File
@@ -8,71 +8,93 @@ Hier sind mehrere Möglichkeiten, das zu tun.
Sie können `examples` („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden.
=== "Python 3.10+ Pydantic v2"
//// tab | Python 3.10+ Pydantic v2
```Python hl_lines="13-24"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
```
```Python hl_lines="13-24"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
```
=== "Python 3.10+ Pydantic v1"
////
```Python hl_lines="13-23"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
```
//// tab | Python 3.10+ Pydantic v1
=== "Python 3.8+ Pydantic v2"
```Python hl_lines="13-23"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
```
```Python hl_lines="15-26"
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
```
////
=== "Python 3.8+ Pydantic v1"
//// tab | Python 3.8+ Pydantic v2
```Python hl_lines="15-25"
{!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
```
```Python hl_lines="15-26"
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
```
////
//// tab | Python 3.8+ Pydantic v1
```Python hl_lines="15-25"
{!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
```
////
Diese zusätzlichen Informationen werden unverändert zum für dieses Modell ausgegebenen **JSON-Schema** hinzugefügt und in der API-Dokumentation verwendet.
=== "Pydantic v2"
//// tab | Pydantic v2
In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydantic-Dokumentation: Configuration</a>.
In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydantic-Dokumentation: Configuration</a>.
Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
=== "Pydantic v1"
////
In Pydantic Version 1 würden Sie eine interne Klasse `Config` und `schema_extra` verwenden, wie beschrieben in <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic-Dokumentation: Schema customization</a>.
//// tab | Pydantic v1
Sie können `schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
In Pydantic Version 1 würden Sie eine interne Klasse `Config` und `schema_extra` verwenden, wie beschrieben in <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic-Dokumentation: Schema customization</a>.
!!! tip "Tipp"
Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen.
Sie können `schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen.
////
!!! info
OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist.
/// tip | "Tipp"
Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓
Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen.
Mehr erfahren Sie am Ende dieser Seite.
Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen.
///
/// info
OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist.
Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓
Mehr erfahren Sie am Ende dieser Seite.
///
## Zusätzliche Argumente für `Field`
Wenn Sie `Field()` mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche `examples` deklarieren:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="2 8-11"
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
```
```Python hl_lines="2 8-11"
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="4 10-13"
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
```
//// tab | Python 3.8+
```Python hl_lines="4 10-13"
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
```
////
## `examples` im JSON-Schema – OpenAPI
@@ -92,41 +114,57 @@ können Sie auch eine Gruppe von `examples` mit zusätzlichen Informationen dekl
Hier übergeben wir `examples`, welches ein einzelnes Beispiel für die in `Body()` erwarteten Daten enthält:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="22-29"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
```
```Python hl_lines="22-29"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="22-29"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="22-29"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
```
```Python hl_lines="23-30"
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="23-30"
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
```
```Python hl_lines="18-25"
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="20-27"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="18-25"
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="20-27"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```
////
### Beispiel in der Dokumentations-Benutzeroberfläche
@@ -138,41 +176,57 @@ Mit jeder der oben genannten Methoden würde es in `/docs` so aussehen:
Sie können natürlich auch mehrere `examples` übergeben:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="23-38"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
```
```Python hl_lines="23-38"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="23-38"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="23-38"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
```
```Python hl_lines="24-39"
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="24-39"
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
```
```Python hl_lines="19-34"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="21-36"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19-34"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="21-36"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```
////
Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** für diese Body-Daten.
@@ -213,41 +267,57 @@ Jedes spezifische Beispiel-`dict` in den `examples` kann Folgendes enthalten:
Sie können es so verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py310.py!}
```
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py39.py!}
```
```Python hl_lines="24-50"
{!> ../../../docs_src/schema_extra_example/tutorial005_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="24-50"
{!> ../../../docs_src/schema_extra_example/tutorial005_an.py!}
```
```Python hl_lines="19-45"
{!> ../../../docs_src/schema_extra_example/tutorial005_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="21-47"
{!> ../../../docs_src/schema_extra_example/tutorial005.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19-45"
{!> ../../../docs_src/schema_extra_example/tutorial005_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="21-47"
{!> ../../../docs_src/schema_extra_example/tutorial005.py!}
```
////
### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche
@@ -257,17 +327,23 @@ Wenn `openapi_examples` zu `Body()` hinzugefügt wird, würde `/docs` so aussehe
## Technische Details
!!! tip "Tipp"
Wenn Sie bereits **FastAPI** Version **0.99.0 oder höher** verwenden, können Sie diese Details wahrscheinlich **überspringen**.
/// tip | "Tipp"
Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war.
Wenn Sie bereits **FastAPI** Version **0.99.0 oder höher** verwenden, können Sie diese Details wahrscheinlich **überspringen**.
Sie können dies als eine kurze **Geschichtsstunde** zu OpenAPI und JSON Schema betrachten. 🤓
Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war.
!!! warning "Achtung"
Dies sind sehr technische Details zu den Standards **JSON Schema** und **OpenAPI**.
Sie können dies als eine kurze **Geschichtsstunde** zu OpenAPI und JSON Schema betrachten. 🤓
Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne.
///
/// warning | "Achtung"
Dies sind sehr technische Details zu den Standards **JSON Schema** und **OpenAPI**.
Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne.
///
Vor OpenAPI 3.1.0 verwendete OpenAPI eine ältere und modifizierte Version von **JSON Schema**.
@@ -285,8 +361,11 @@ OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Sp
* `File()`
* `Form()`
!!! info
Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`.
/// info
Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`.
///
### JSON Schemas Feld `examples`
@@ -298,10 +377,13 @@ Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdef
Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`e** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben).
!!! info
Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉).
/// info
Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0.
Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉).
Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0.
///
### Pydantic- und FastAPI-`examples`
+114 -66
View File
@@ -20,35 +20,47 @@ Lassen Sie uns zunächst einfach den Code verwenden und sehen, wie er funktionie
Kopieren Sie das Beispiel in eine Datei `main.py`:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
```Python
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python
{!> ../../../docs_src/security/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python
{!> ../../../docs_src/security/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python
{!> ../../../docs_src/security/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
{!> ../../../docs_src/security/tutorial001.py!}
```
////
## Ausführen
!!! info
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
/// info
Z. B. `pip install python-multipart`.
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
Z. B. `pip install python-multipart`.
Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
///
Führen Sie das Beispiel aus mit:
@@ -70,17 +82,23 @@ Sie werden etwa Folgendes sehen:
<img src="/img/tutorial/security/image01.png">
!!! check "Authorize-Button!"
Sie haben bereits einen glänzenden, neuen „Authorize“-Button.
/// check | "Authorize-Button!"
Und Ihre *Pfadoperation* hat in der oberen rechten Ecke ein kleines Schloss, auf das Sie klicken können.
Sie haben bereits einen glänzenden, neuen „Authorize“-Button.
Und Ihre *Pfadoperation* hat in der oberen rechten Ecke ein kleines Schloss, auf das Sie klicken können.
///
Und wenn Sie darauf klicken, erhalten Sie ein kleines Anmeldeformular zur Eingabe eines `username` und `password` (und anderer optionaler Felder):
<img src="/img/tutorial/security/image02.png">
!!! note "Hinweis"
Es spielt keine Rolle, was Sie in das Formular eingeben, es wird noch nicht funktionieren. Wir kommen dahin.
/// note | "Hinweis"
Es spielt keine Rolle, was Sie in das Formular eingeben, es wird noch nicht funktionieren. Wir kommen dahin.
///
Dies ist natürlich nicht das Frontend für die Endbenutzer, aber es ist ein großartiges automatisches Tool, um Ihre gesamte API interaktiv zu dokumentieren.
@@ -122,53 +140,71 @@ Betrachten wir es also aus dieser vereinfachten Sicht:
In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`.
!!! info
Ein „Bearer“-Token ist nicht die einzige Option.
/// info
Aber es ist die beste für unseren Anwendungsfall.
Ein „Bearer“-Token ist nicht die einzige Option.
Und es ist wahrscheinlich auch für die meisten anderen Anwendungsfälle die beste, es sei denn, Sie sind ein OAuth2-Experte und wissen genau, warum es eine andere Option gibt, die Ihren Anforderungen besser entspricht.
Aber es ist die beste für unseren Anwendungsfall.
In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen brauchen.
Und es ist wahrscheinlich auch für die meisten anderen Anwendungsfälle die beste, es sei denn, Sie sind ein OAuth2-Experte und wissen genau, warum es eine andere Option gibt, die Ihren Anforderungen besser entspricht.
In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen brauchen.
///
Wenn wir eine Instanz der Klasse `OAuth2PasswordBearer` erstellen, übergeben wir den Parameter `tokenUrl`. Dieser Parameter enthält die URL, die der Client (das Frontend, das im Browser des Benutzers ausgeführt wird) verwendet, wenn er den `username` und das `password` sendet, um einen Token zu erhalten.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="8"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
```Python hl_lines="8"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="7"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="7"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="6"
{!> ../../../docs_src/security/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
!!! tip "Tipp"
Hier bezieht sich `tokenUrl="token"` auf eine relative URL `token`, die wir noch nicht erstellt haben. Da es sich um eine relative URL handelt, entspricht sie `./token`.
/// tip | "Tipp"
Da wir eine relative URL verwenden, würde sich das, wenn sich Ihre API unter `https://example.com/` befindet, auf `https://example.com/token` beziehen. Wenn sich Ihre API jedoch unter `https://example.com/api/v1/` befände, würde es sich auf `https://example.com/api/v1/token` beziehen.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
Die Verwendung einer relativen URL ist wichtig, um sicherzustellen, dass Ihre Anwendung auch in einem fortgeschrittenen Anwendungsfall, wie [hinter einem Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}, weiterhin funktioniert.
///
```Python hl_lines="6"
{!> ../../../docs_src/security/tutorial001.py!}
```
////
/// tip | "Tipp"
Hier bezieht sich `tokenUrl="token"` auf eine relative URL `token`, die wir noch nicht erstellt haben. Da es sich um eine relative URL handelt, entspricht sie `./token`.
Da wir eine relative URL verwenden, würde sich das, wenn sich Ihre API unter `https://example.com/` befindet, auf `https://example.com/token` beziehen. Wenn sich Ihre API jedoch unter `https://example.com/api/v1/` befände, würde es sich auf `https://example.com/api/v1/token` beziehen.
Die Verwendung einer relativen URL ist wichtig, um sicherzustellen, dass Ihre Anwendung auch in einem fortgeschrittenen Anwendungsfall, wie [hinter einem Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}, weiterhin funktioniert.
///
Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern deklariert, dass die URL `/token` diejenige sein wird, die der Client verwenden soll, um den Token abzurufen. Diese Information wird in OpenAPI und dann in den interaktiven API-Dokumentationssystemen verwendet.
Wir werden demnächst auch die eigentliche Pfadoperation erstellen.
!!! info
Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`.
/// info
Das liegt daran, dass FastAPI denselben Namen wie in der OpenAPI-Spezifikation verwendet. Sodass Sie, wenn Sie mehr über eines dieser Sicherheitsschemas herausfinden möchten, den Namen einfach kopieren und einfügen können, um weitere Informationen darüber zu erhalten.
Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`.
Das liegt daran, dass FastAPI denselben Namen wie in der OpenAPI-Spezifikation verwendet. Sodass Sie, wenn Sie mehr über eines dieser Sicherheitsschemas herausfinden möchten, den Namen einfach kopieren und einfügen können, um weitere Informationen darüber zu erhalten.
///
Die Variable `oauth2_scheme` ist eine Instanz von `OAuth2PasswordBearer`, aber auch ein „Callable“.
@@ -184,35 +220,47 @@ Es kann also mit `Depends` verwendet werden.
Jetzt können Sie dieses `oauth2_scheme` als Abhängigkeit `Depends` übergeben.
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
////
Diese Abhängigkeit stellt einen `str` bereit, der dem Parameter `token` der *Pfadoperation-Funktion* zugewiesen wird.
**FastAPI** weiß, dass es diese Abhängigkeit verwenden kann, um ein „Sicherheitsschema“ im OpenAPI-Schema (und der automatischen API-Dokumentation) zu definieren.
!!! info "Technische Details"
**FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt.
/// info | "Technische Details"
Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische API-Dokumentation), erben von `SecurityBase`, so weiß **FastAPI**, wie es sie in OpenAPI integrieren muss.
**FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt.
Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische API-Dokumentation), erben von `SecurityBase`, so weiß **FastAPI**, wie es sie in OpenAPI integrieren muss.
///
## Was es macht
+235 -140
View File
@@ -2,26 +2,35 @@
Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` überreicht:
=== "Python 3.9+"
//// tab | Python 3.9+
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
////
Aber das ist immer noch nicht so nützlich.
@@ -33,41 +42,57 @@ Erstellen wir zunächst ein Pydantic-Benutzermodell.
So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
```Python hl_lines="5 13-17"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="5 13-17"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
```Python hl_lines="3 10-14"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3 10-14"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002.py!}
```
////
## Eine `get_current_user`-Abhängigkeit erstellen
@@ -79,135 +104,189 @@ Erinnern Sie sich, dass Abhängigkeiten Unterabhängigkeiten haben können?
So wie wir es zuvor in der *Pfadoperation* direkt gemacht haben, erhält unsere neue Abhängigkeit `get_current_user` von der Unterabhängigkeit `oauth2_scheme` einen `token` vom Typ `str`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
```Python hl_lines="26"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="26"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
```Python hl_lines="23"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="23"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002.py!}
```
////
## Den Benutzer holen
`get_current_user` wird eine von uns erstellte (gefakte) Hilfsfunktion verwenden, welche einen Token vom Typ `str` entgegennimmt und unser Pydantic-`User`-Modell zurückgibt:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
```Python hl_lines="20-23 27-28"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="20-23 27-28"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
```Python hl_lines="17-20 24-25"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="17-20 24-25"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002.py!}
```
////
## Den aktuellen Benutzer einfügen
Und jetzt können wir wiederum `Depends` mit unserem `get_current_user` in der *Pfadoperation* verwenden:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
```Python hl_lines="32"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="32"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
```Python hl_lines="29"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="29"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002.py!}
```
////
Beachten Sie, dass wir als Typ von `current_user` das Pydantic-Modell `User` deklarieren.
Das wird uns innerhalb der Funktion bei Codevervollständigung und Typprüfungen helfen.
!!! tip "Tipp"
Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden.
/// tip | "Tipp"
Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt.
Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden.
!!! check
Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben.
Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt.
Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen Typ von Daten zurückgeben kann.
///
/// check
Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben.
Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen Typ von Daten zurückgeben kann.
///
## Andere Modelle
@@ -241,41 +320,57 @@ Und alle (oder beliebige Teile davon) können Vorteil ziehen aus der Wiederverwe
Und alle diese Tausenden von *Pfadoperationen* können nur drei Zeilen lang sein:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
```Python hl_lines="31-33"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="31-33"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
```Python hl_lines="28-30"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="28-30"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002.py!}
```
////
## Zusammenfassung
+10 -5
View File
@@ -32,9 +32,11 @@ Heutzutage ist es nicht sehr populär und wird kaum verwendet.
OAuth2 spezifiziert nicht, wie die Kommunikation verschlüsselt werden soll, sondern erwartet, dass Ihre Anwendung mit HTTPS bereitgestellt wird.
!!! tip "Tipp"
Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traefik und Let's Encrypt kostenlos einrichten.
/// tip | "Tipp"
Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traefik und Let's Encrypt kostenlos einrichten.
///
## OpenID Connect
@@ -87,10 +89,13 @@ OpenAPI definiert die folgenden Sicherheitsschemas:
* Diese automatische Erkennung ist es, die in der OpenID Connect Spezifikation definiert ist.
!!! tip "Tipp"
Auch die Integration anderer Authentifizierungs-/Autorisierungsanbieter wie Google, Facebook, Twitter, GitHub, usw. ist möglich und relativ einfach.
/// tip | "Tipp"
Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsanbieter wie solche aufzubauen, aber **FastAPI** reicht Ihnen die Tools, das einfach zu erledigen, während Ihnen die schwere Arbeit abgenommen wird.
Auch die Integration anderer Authentifizierungs-/Autorisierungsanbieter wie Google, Facebook, Twitter, GitHub, usw. ist möglich und relativ einfach.
Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsanbieter wie solche aufzubauen, aber **FastAPI** reicht Ihnen die Tools, das einfach zu erledigen, während Ihnen die schwere Arbeit abgenommen wird.
///
## **FastAPI** Tools
+195 -113
View File
@@ -44,10 +44,13 @@ $ pip install "python-jose[cryptography]"
Hier verwenden wir das empfohlene: <a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>.
!!! tip "Tipp"
Dieses Tutorial verwendete zuvor <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
/// tip | "Tipp"
Es wurde jedoch aktualisiert, stattdessen python-jose zu verwenden, da dieses alle Funktionen von PyJWT sowie einige Extras bietet, die Sie später möglicherweise benötigen, wenn Sie Integrationen mit anderen Tools erstellen.
Dieses Tutorial verwendete zuvor <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
Es wurde jedoch aktualisiert, stattdessen python-jose zu verwenden, da dieses alle Funktionen von PyJWT sowie einige Extras bietet, die Sie später möglicherweise benötigen, wenn Sie Integrationen mit anderen Tools erstellen.
///
## Passwort-Hashing
@@ -83,12 +86,15 @@ $ pip install "passlib[bcrypt]"
</div>
!!! tip "Tipp"
Mit `passlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheit-Plugin, oder vielen anderen erstellt wurden.
/// tip | "Tipp"
So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden.
Mit `passlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheit-Plugin, oder vielen anderen erstellt wurden.
Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ihre **FastAPI**-Anwendung anmelden.
So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden.
Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ihre **FastAPI**-Anwendung anmelden.
///
## Die Passwörter hashen und überprüfen
@@ -96,12 +102,15 @@ Importieren Sie die benötigten Tools aus `passlib`.
Erstellen Sie einen PassLib-„Kontext“. Der wird für das Hashen und Verifizieren von Passwörtern verwendet.
!!! tip "Tipp"
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
/// tip | "Tipp"
Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen.
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
Und mit allen gleichzeitig kompatibel sein.
Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen.
Und mit allen gleichzeitig kompatibel sein.
///
Erstellen Sie eine Hilfsfunktion, um ein vom Benutzer stammendes Passwort zu hashen.
@@ -109,44 +118,63 @@ Und eine weitere, um zu überprüfen, ob ein empfangenes Passwort mit dem gespei
Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
```Python hl_lines="7 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="7 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
```Python hl_lines="6 47 54-55 58-59 68-74"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! note "Hinweis"
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
///
```Python hl_lines="6 47 54-55 58-59 68-74"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004.py!}
```
////
/// note | "Hinweis"
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
///
## JWT-Token verarbeiten
@@ -176,41 +204,57 @@ Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verw
Erstellen Sie eine Hilfsfunktion, um einen neuen Zugriffstoken zu generieren.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
```Python hl_lines="6 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="6 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
```Python hl_lines="5 11-13 27-29 77-85"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="5 11-13 27-29 77-85"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004.py!}
```
////
## Die Abhängigkeiten aktualisieren
@@ -220,41 +264,57 @@ Dekodieren Sie den empfangenen Token, validieren Sie ihn und geben Sie den aktue
Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
```Python hl_lines="88-105"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="88-105"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004.py!}
```
////
## Die *Pfadoperation* `/token` aktualisieren
@@ -262,41 +322,57 @@ Erstellen Sie ein <abbr title="Zeitdifferenz">`timedelta`</abbr> mit der Ablaufz
Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurück.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
```Python hl_lines="118-133"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="118-133"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
```Python hl_lines="114-129"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="115-130"
{!> ../../../docs_src/security/tutorial004.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="114-129"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="115-130"
{!> ../../../docs_src/security/tutorial004.py!}
```
////
### Technische Details zum JWT-„Subjekt“ `sub`
@@ -335,8 +411,11 @@ Verwenden Sie die Anmeldeinformationen:
Benutzername: `johndoe`
Passwort: `secret`.
!!! check
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version.
/// check
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version.
///
<img src="/img/tutorial/security/image08.png">
@@ -357,8 +436,11 @@ Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Dat
<img src="/img/tutorial/security/image10.png">
!!! note "Hinweis"
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt.
/// note | "Hinweis"
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt.
///
## Fortgeschrittene Verwendung mit `scopes`
+258 -154
View File
@@ -32,14 +32,17 @@ Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu
* `instagram_basic` wird von Facebook / Instagram verwendet.
* `https://www.googleapis.com/auth/drive` wird von Google verwendet.
!!! info
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
/// info
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
Diese Details sind implementierungsspezifisch.
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
Für OAuth2 sind es einfach nur Strings.
Diese Details sind implementierungsspezifisch.
Für OAuth2 sind es einfach nur Strings.
///
## Code, um `username` und `password` entgegenzunehmen.
@@ -49,41 +52,57 @@ Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um
Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als Abhängigkeit mit `Depends` in der *Pfadoperation* für `/token`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
```Python hl_lines="4 79"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="4 79"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```
////
`OAuth2PasswordRequestForm` ist eine Klassenabhängigkeit, die einen Formularbody deklariert mit:
@@ -92,29 +111,38 @@ Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als A
* Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings.
* Einem optionalen `grant_type` („Art der Anmeldung“).
!!! tip "Tipp"
Die OAuth2-Spezifikation *erfordert* tatsächlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht.
/// tip | "Tipp"
Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`.
Die OAuth2-Spezifikation *erfordert* tatsächlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht.
Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`.
///
* Eine optionale `client_id` (benötigen wir für unser Beispiel nicht).
* Ein optionales `client_secret` (benötigen wir für unser Beispiel nicht).
!!! info
`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`.
/// info
`OAuth2PasswordBearer` lässt **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefügt.
`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`.
Aber `OAuth2PasswordRequestForm` ist nur eine Klassenabhängigkeit, die Sie selbst hätten schreiben können, oder Sie hätten `Form`ular-Parameter direkt deklarieren können.
`OAuth2PasswordBearer` lässt **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefügt.
Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt.
Aber `OAuth2PasswordRequestForm` ist nur eine Klassenabhängigkeit, die Sie selbst hätten schreiben können, oder Sie hätten `Form`ular-Parameter direkt deklarieren können.
Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt.
///
### Die Formulardaten verwenden
!!! tip "Tipp"
Die Instanz der Klassenabhängigkeit `OAuth2PasswordRequestForm` verfügt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, über das Attribut `scopes` mit einer tatsächlichen Liste von Strings, einem für jeden gesendeten Scope.
/// tip | "Tipp"
In diesem Beispiel verwenden wir keine `scopes`, aber die Funktionalität ist vorhanden, wenn Sie sie benötigen.
Die Instanz der Klassenabhängigkeit `OAuth2PasswordRequestForm` verfügt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, über das Attribut `scopes` mit einer tatsächlichen Liste von Strings, einem für jeden gesendeten Scope.
In diesem Beispiel verwenden wir keine `scopes`, aber die Funktionalität ist vorhanden, wenn Sie sie benötigen.
///
Rufen Sie nun die Benutzerdaten aus der (gefakten) Datenbank ab, für diesen `username` aus dem Formularfeld.
@@ -122,41 +150,57 @@ Wenn es keinen solchen Benutzer gibt, geben wir die Fehlermeldung „Incorrect u
Für den Fehler verwenden wir die Exception `HTTPException`:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
```Python hl_lines="3 80-82"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="3 80-82"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```
////
### Das Passwort überprüfen
@@ -182,41 +226,57 @@ Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter
Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich).
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
```Python hl_lines="83-86"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="83-86"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```
////
#### Über `**user_dict`
@@ -234,8 +294,11 @@ UserInDB(
)
```
!!! info
Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}.
/// info
Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}.
///
## Den Token zurückgeben
@@ -247,55 +310,77 @@ Und es sollte einen `access_token` haben, mit einem String, der unseren Zugriffs
In diesem einfachen Beispiel gehen wir einfach völlig unsicher vor und geben denselben `username` wie der Token zurück.
!!! tip "Tipp"
Im nächsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und <abbr title="JSON Web Tokens">JWT</abbr>-Tokens.
/// tip | "Tipp"
Aber konzentrieren wir uns zunächst auf die spezifischen Details, die wir benötigen.
Im nächsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und <abbr title="JSON Web Tokens">JWT</abbr>-Tokens.
=== "Python 3.10+"
Aber konzentrieren wir uns zunächst auf die spezifischen Details, die wir benötigen.
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
///
=== "Python 3.9+"
//// tab | Python 3.10+
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.8+"
////
```Python hl_lines="88"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
//// tab | Python 3.9+
=== "Python 3.10+ nicht annotiert"
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
//// tab | Python 3.8+
=== "Python 3.8+ nicht annotiert"
```Python hl_lines="88"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Gemäß der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurückgeben, genau wie in diesem Beispiel.
/// tip | "Tipp"
Das müssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-Schlüssel verwenden.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
Es ist fast das Einzige, woran Sie denken müssen, es selbst richtigzumachen und die Spezifikationen einzuhalten.
///
Den Rest erledigt **FastAPI** für Sie.
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```
////
/// tip | "Tipp"
Gemäß der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurückgeben, genau wie in diesem Beispiel.
Das müssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-Schlüssel verwenden.
Es ist fast das Einzige, woran Sie denken müssen, es selbst richtigzumachen und die Spezifikationen einzuhalten.
Den Rest erledigt **FastAPI** für Sie.
///
## Die Abhängigkeiten aktualisieren
@@ -309,56 +394,75 @@ Beide Abhängigkeiten geben nur dann einen HTTP-Error zurück, wenn der Benutzer
In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer existiert, korrekt authentifiziert wurde und aktiv ist:
=== "Python 3.10+"
//// tab | Python 3.10+
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
////
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
```Python hl_lines="59-67 70-75 95"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python hl_lines="59-67 70-75 95"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
```Python hl_lines="56-64 67-70 88"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python hl_lines="58-66 69-72 90"
{!> ../../../docs_src/security/tutorial003.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
!!! info
Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation.
///
Jeder HTTP-(Fehler-)Statuscode 401 „UNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurückgeben.
```Python hl_lines="56-64 67-70 88"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten.
////
Sie können diesen zusätzlichen Header tatsächlich weglassen und es würde trotzdem funktionieren.
//// tab | Python 3.8+ nicht annotiert
Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen.
/// tip | "Tipp"
Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte für Sie oder Ihre Benutzer jetzt oder in der Zukunft nützlich sein.
Bevorzugen Sie die `Annotated`-Version, falls möglich.
Das ist der Vorteil von Standards ...
///
```Python hl_lines="58-66 69-72 90"
{!> ../../../docs_src/security/tutorial003.py!}
```
////
/// info
Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation.
Jeder HTTP-(Fehler-)Statuscode 401 „UNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurückgeben.
Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten.
Sie können diesen zusätzlichen Header tatsächlich weglassen und es würde trotzdem funktionieren.
Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen.
Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte für Sie oder Ihre Benutzer jetzt oder in der Zukunft nützlich sein.
Das ist der Vorteil von Standards ...
///
## Es in Aktion sehen
+6 -3
View File
@@ -11,10 +11,13 @@ Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisc
{!../../../docs_src/static_files/tutorial001.py!}
```
!!! note "Technische Details"
Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden.
/// note | "Technische Details"
**FastAPI** stellt dasselbe `starlette.staticfiles` auch via `fastapi.staticfiles` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden.
**FastAPI** stellt dasselbe `starlette.staticfiles` auch via `fastapi.staticfiles` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
///
### Was ist „Mounten“?
+70 -39
View File
@@ -8,10 +8,13 @@ Damit können Sie <a href="https://docs.pytest.org/" class="external-link" targe
## Verwendung von `TestClient`
!!! info
Um `TestClient` zu verwenden, installieren Sie zunächst <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
/// info
Z. B. `pip install httpx`.
Um `TestClient` zu verwenden, installieren Sie zunächst <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
Z. B. `pip install httpx`.
///
Importieren Sie `TestClient`.
@@ -27,20 +30,29 @@ Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken,
{!../../../docs_src/app_testing/tutorial001.py!}
```
!!! tip "Tipp"
Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind.
/// tip | "Tipp"
Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden.
Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind.
Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen.
Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden.
!!! note "Technische Details"
Sie könnten auch `from starlette.testclient import TestClient` verwenden.
Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen.
**FastAPI** stellt denselben `starlette.testclient` auch via `fastapi.testclient` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
///
!!! tip "Tipp"
Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer.
/// note | "Technische Details"
Sie könnten auch `from starlette.testclient import TestClient` verwenden.
**FastAPI** stellt denselben `starlette.testclient` auch via `fastapi.testclient` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
///
/// tip | "Tipp"
Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer.
///
## Tests separieren
@@ -110,41 +122,57 @@ Sie verfügt über eine `POST`-Operation, die mehrere Fehler zurückgeben könnt
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
=== "Python 3.10+"
//// tab | Python 3.10+
```Python
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
```
```Python
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
```
=== "Python 3.9+"
////
```Python
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
```
//// tab | Python 3.9+
=== "Python 3.8+"
```Python
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
```
```Python
{!> ../../../docs_src/app_testing/app_b_an/main.py!}
```
////
=== "Python 3.10+ nicht annotiert"
//// tab | Python 3.8+
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
```Python
{!> ../../../docs_src/app_testing/app_b_an/main.py!}
```
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
////
=== "Python 3.8+ nicht annotiert"
//// tab | Python 3.10+ nicht annotiert
!!! tip "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
/// tip | "Tipp"
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
////
### Erweiterte Testdatei
@@ -168,10 +196,13 @@ Z. B.:
Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von `httpx` oder dem `TestClient`) finden Sie in der <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX-Dokumentation</a>.
!!! info
Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
/// info
Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den `jsonable_encoder` verwenden, der in [JSON-kompatibler Encoder](encoder.md){.internal-link target=_blank} beschrieben wird.
Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den `jsonable_encoder` verwenden, der in [JSON-kompatibler Encoder](encoder.md){.internal-link target=_blank} beschrieben wird.
///
## Tests ausführen