📝 Update prompts and German translation (#14015)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
authored and GitHub committed 2025-09-20 17:10:09 +02:00
1 parent 4c175319f5
commit 9b1234d7d0
112 files changed
+5303 -3025

No files matched your search

+14 -12
View File
@@ -1,8 +1,8 @@
# Hintergrundtasks
# Hintergrundtasks { #background-tasks }
Sie können Hintergrundtasks (Hintergrund-Aufgaben) definieren, die *nach* der Rückgabe einer Response ausgeführt werden sollen.
Sie können <abbr title="Hintergrund-Aufgaben">Hintergrundtasks</abbr> definieren, die *nach* der Rückgabe einer <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> ausgeführt werden sollen.
Das ist nützlich für Vorgänge, die nach einem Request ausgeführt werden müssen, bei denen der Client jedoch nicht unbedingt auf den Abschluss des Vorgangs warten muss, bevor er die Response erhält.
Das ist nützlich für Vorgänge, die nach einem <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> ausgeführt werden müssen, bei denen der Client jedoch nicht unbedingt auf den Abschluss des Vorgangs warten muss, bevor er die Response erhält.
Hierzu zählen beispielsweise:
@@ -11,7 +11,7 @@ Hierzu zählen beispielsweise:
* Daten verarbeiten:
* Angenommen, Sie erhalten eine Datei, die einen langsamen Prozess durchlaufen muss. Sie können als Response „Accepted“ (HTTP 202) zurückgeben und die Datei im Hintergrund verarbeiten.
## `BackgroundTasks` verwenden
## `BackgroundTasks` verwenden { #using-backgroundtasks }
Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`:
@@ -19,7 +19,7 @@ Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter i
**FastAPI** erstellt für Sie das Objekt vom Typ `BackgroundTasks` und übergibt es als diesen Parameter.
## Eine Taskfunktion erstellen
## Eine Taskfunktion erstellen { #create-a-task-function }
Erstellen Sie eine Funktion, die als Hintergrundtask ausgeführt werden soll.
@@ -33,7 +33,7 @@ Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir di
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
## Den Hintergrundtask hinzufügen
## Den Hintergrundtask hinzufügen { #add-the-background-task }
Übergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt:
@@ -45,21 +45,23 @@ Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir di
* Eine beliebige Folge von Argumenten, die der Reihe nach an die Taskfunktion übergeben werden sollen (`email`).
* Alle Schlüsselwort-Argumente, die an die Taskfunktion übergeben werden sollen (`message="some notification"`).
## Dependency Injection
## Dependency Injection { #dependency-injection }
Die Verwendung von `BackgroundTasks` funktioniert auch mit dem <abbr title="Einbringen von Abhängigkeiten">Dependency Injection</abbr> System. Sie können einen Parameter vom Typ `BackgroundTasks` auf mehreren Ebenen deklarieren: in einer *Pfadoperation-Funktion*, in einer Abhängigkeit (Dependable), in einer Unterabhängigkeit usw.
**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:
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
In obigem Beispiel werden die Nachrichten, *nachdem* die Response gesendet wurde, in die Datei `log.txt` geschrieben.
Wenn im Request ein Query-Parameter enthalten war, wird dieser in einem Hintergrundtask in das Log geschrieben.
Und dann schreibt ein weiterer Hintergrundtask, der in der *Pfadoperation-Funktion* erstellt wird, eine Nachricht unter Verwendung des Pfad-Parameters `email`.
## Technische Details
## Technische Details { #technical-details }
Die Klasse `BackgroundTasks` stammt direkt von <a href="https://www.starlette.io/background/" class="external-link" target="_blank">`starlette.background`</a>.
@@ -69,16 +71,16 @@ Indem Sie nur `BackgroundTasks` (und nicht `BackgroundTask`) verwenden, ist es d
Es ist immer noch möglich, `BackgroundTask` allein in FastAPI zu verwenden, aber Sie müssen das Objekt in Ihrem Code erstellen und eine Starlette-`Response` zurückgeben, die es enthält.
Weitere Details finden Sie in der <a href="https://www.starlette.io/background/" class="external-link" target="_blank">offiziellen Starlette-Dokumentation für Hintergrundtasks</a>.
Weitere Details finden Sie in <a href="https://www.starlette.io/background/" class="external-link" target="_blank">Starlettes offizieller Dokumentation für Hintergrundtasks</a>.
## Vorbehalt
## Vorbehalt { #caveat }
Wenn Sie umfangreiche Hintergrundberechnungen durchführen müssen und diese nicht unbedingt vom selben Prozess ausgeführt werden müssen (z. B. müssen Sie Speicher, Variablen, usw. nicht gemeinsam nutzen), könnte die Verwendung anderer größerer Tools wie z. B. <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a> von Vorteil sein.
Sie erfordern in der Regel komplexere Konfigurationen und einen Nachrichten-/Job-Queue-Manager wie RabbitMQ oder Redis, ermöglichen Ihnen jedoch die Ausführung von Hintergrundtasks in mehreren Prozessen und insbesondere auf mehreren Servern.
Wenn Sie jedoch über dieselbe **FastAPI**-Anwendung auf Variablen und Objekte zugreifen oder kleine Hintergrundtasks ausführen müssen (z. B. das Senden einer E-Mail-Benachrichtigung), können Sie einfach `BackgroundTasks` verwenden.
Wenn Sie jedoch über dieselbe **FastAPI**-App auf Variablen und Objekte zugreifen oder kleine Hintergrundtasks ausführen müssen (z. B. das Senden einer E-Mail-Benachrichtigung), können Sie einfach `BackgroundTasks` verwenden.
## Zusammenfassung
## Zusammenfassung { #recap }
Importieren und verwenden Sie `BackgroundTasks` mit Parametern in *Pfadoperation-Funktionen* und Abhängigkeiten, um Hintergrundtasks hinzuzufügen.
+31 -32
View File
@@ -1,16 +1,16 @@
# Größere Anwendungen – mehrere Dateien
# Größere Anwendungen – mehrere Dateien { #bigger-applications-multiple-files }
Wenn Sie eine Anwendung oder eine Web-API erstellen, ist es selten der Fall, dass Sie alles in einer einzigen Datei unterbringen können.
**FastAPI** bietet ein praktisches Werkzeug zur Strukturierung Ihrer Anwendung bei gleichzeitiger Wahrung der Flexibilität.
/// info
/// info | Info
Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints.
///
## Eine Beispiel-Dateistruktur
## Eine Beispiel-Dateistruktur { #an-example-file-structure }
Nehmen wir an, Sie haben eine Dateistruktur wie diese:
@@ -71,7 +71,7 @@ Die gleiche Dateistruktur mit Kommentaren:
│   └── admin.py # „admin“-Submodul, z. B. import app.internal.admin
```
## `APIRouter`
## `APIRouter` { #apirouter }
Nehmen wir an, die Datei, die nur für die Verwaltung von Benutzern zuständig ist, ist das Submodul unter `/app/routers/users.py`.
@@ -81,7 +81,7 @@ Aber es ist immer noch Teil derselben **FastAPI**-Anwendung/Web-API (es ist Teil
Sie können die *Pfadoperationen* für dieses Modul mit `APIRouter` erstellen.
### `APIRouter` importieren
### `APIRouter` importieren { #import-apirouter }
Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`:
@@ -89,7 +89,7 @@ Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie m
{!../../docs_src/bigger_applications/app/routers/users.py!}
```
### *Pfadoperationen* mit `APIRouter`
### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter }
Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren.
@@ -113,7 +113,7 @@ In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beli
Wir werden diesen `APIRouter` in die Hauptanwendung `FastAPI` einbinden, aber zuerst kümmern wir uns um die Abhängigkeiten und einen anderen `APIRouter`.
## Abhängigkeiten
## Abhängigkeiten { #dependencies }
Wir sehen, dass wir einige Abhängigkeiten benötigen, die an mehreren Stellen der Anwendung verwendet werden.
@@ -159,7 +159,7 @@ Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](secu
///
## Ein weiteres Modul mit `APIRouter`.
## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter }
Nehmen wir an, Sie haben im Modul unter `app/routers/items.py` auch die Endpunkte, die für die Verarbeitung von Artikeln („Items“) aus Ihrer Anwendung vorgesehen sind.
@@ -199,7 +199,7 @@ Das Präfix lautet in diesem Fall also `/items`.
Wir können auch eine Liste von `tags` und zusätzliche `responses` hinzufügen, die auf alle in diesem Router enthaltenen *Pfadoperationen* angewendet werden.
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.
Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> ausgeführt/aufgelöst werden.
/// tip | Tipp
@@ -228,13 +228,13 @@ Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten:
///
/// check
/// check | Testen
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
### Die Abhängigkeiten importieren { #import-the-dependencies }
Der folgende Code befindet sich im Modul `app.routers.items`, also in der Datei `app/routers/items.py`.
@@ -246,7 +246,7 @@ Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
{!../../docs_src/bigger_applications/app/routers/items.py!}
```
#### Wie relative Importe funktionieren
#### Wie relative Importe funktionieren { #how-relative-imports-work }
/// tip | Tipp
@@ -309,7 +309,7 @@ Das würde sich auf ein Paket oberhalb von `app/` beziehen, mit seiner eigenen D
Aber jetzt wissen Sie, wie es funktioniert, sodass Sie relative Importe in Ihren eigenen Anwendungen verwenden können, egal wie komplex diese sind. 🤓
### Einige benutzerdefinierte `tags`, `responses`, und `dependencies` hinzufügen
### Einige benutzerdefinierte `tags`, `responses`, und `dependencies` hinzufügen { #add-some-custom-tags-responses-and-dependencies }
Wir fügen weder das Präfix `/items` noch `tags=["items"]` zu jeder *Pfadoperation* hinzu, da wir sie zum `APIRouter` hinzugefügt haben.
@@ -323,21 +323,21 @@ Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *P
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`.
Und sie wird auch beide <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Responses</abbr> in der Dokumentation haben, eine für `404` und eine für `403`.
///
## Das Haupt-`FastAPI`.
## Das Haupt-`FastAPI` { #the-main-fastapi }
Sehen wir uns nun das Modul unter `app/main.py` an.
Hier importieren und verwenden Sie die Klasse `FastAPI`.
Dies ist die Hauptdatei Ihrer Anwendung, die alles zusammen bindet.
Dies ist die Hauptdatei Ihrer Anwendung, die alles zusammenfügt.
Und da sich der Großteil Ihrer Logik jetzt in seinem eigenen spezifischen Modul befindet, wird die Hauptdatei recht einfach sein.
### `FastAPI` importieren
### `FastAPI` importieren { #import-fastapi }
Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse.
@@ -347,7 +347,7 @@ Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies
{!../../docs_src/bigger_applications/app/main.py!}
```
### Den `APIRouter` importieren
### Den `APIRouter` importieren { #import-the-apirouter }
Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
@@ -357,7 +357,7 @@ Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, können wir einen einzelnen Punkt `.` verwenden, um sie mit „relativen Imports“ zu importieren.
### Wie das Importieren funktioniert
### Wie das Importieren funktioniert { #how-the-importing-works }
Die Sektion:
@@ -381,7 +381,7 @@ Wir könnten sie auch wie folgt importieren:
from app.routers import items, users
```
/// info
/// info | Info
Die erste Version ist ein „relativer Import“:
@@ -399,7 +399,7 @@ Um mehr über Python-Packages und -Module zu erfahren, lesen Sie <a href="https:
///
### Namenskollisionen vermeiden
### Namenskollisionen vermeiden { #avoid-name-collisions }
Wir importieren das Submodul `items` direkt, anstatt nur seine Variable `router` zu importieren.
@@ -420,8 +420,7 @@ Um also beide in derselben Datei verwenden zu können, importieren wir die Submo
{!../../docs_src/bigger_applications/app/main.py!}
```
### Die `APIRouter` für `users` und `items` inkludieren
### Die `APIRouter` für `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items }
Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
@@ -429,7 +428,7 @@ Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
{!../../docs_src/bigger_applications/app/main.py!}
```
/// info
/// info | Info
`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`.
@@ -449,7 +448,7 @@ Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles die
///
/// check
/// check | Testen
Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Performanz machen.
@@ -459,7 +458,7 @@ Es hat also keinen Einfluss auf die Leistung. ⚡
///
### Einen `APIRouter` mit benutzerdefinierten `prefix`, `tags`, `responses` und `dependencies` einfügen
### Einen `APIRouter` mit benutzerdefinierten `prefix`, `tags`, `responses` und `dependencies` einfügen { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
Stellen wir uns nun vor, dass Ihre Organisation Ihnen die Datei `app/internal/admin.py` gegeben hat.
@@ -492,7 +491,7 @@ Dies wirkt sich jedoch nur auf diesen `APIRouter` in unserer Anwendung aus, nich
So könnten beispielsweise andere Projekte denselben `APIRouter` mit einer anderen Authentifizierungsmethode verwenden.
### Eine *Pfadoperation* hinzufügen
### Eine *Pfadoperation* hinzufügen { #include-a-path-operation }
Wir können *Pfadoperationen* auch direkt zur `FastAPI`-App hinzufügen.
@@ -518,14 +517,14 @@ Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ könne
///
## Es in der automatischen API-Dokumentation ansehen
## Es in der automatischen API-Dokumentation testen { #check-the-automatic-api-docs }
Führen Sie nun `uvicorn` aus, indem Sie das Modul `app.main` und die Variable `app` verwenden:
Führen Sie nun Ihre App aus:
<div class="termy">
```console
$ uvicorn app.main:app --reload
$ fastapi dev app/main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
@@ -538,7 +537,7 @@ Sie sehen die automatische API-Dokumentation, einschließlich der Pfade aller Su
<img src="/img/tutorial/bigger-applications/image01.png">
## Den gleichen Router mehrmals mit unterschiedlichem `prefix` inkludieren
## Den gleichen Router mehrmals mit unterschiedlichem `prefix` inkludieren { #include-the-same-router-multiple-times-with-different-prefix }
Sie können `.include_router()` auch mehrmals mit *demselben* Router und unterschiedlichen Präfixen verwenden.
@@ -546,7 +545,7 @@ Dies könnte beispielsweise nützlich sein, um dieselbe API unter verschiedenen
Dies ist eine fortgeschrittene Verwendung, die Sie möglicherweise nicht wirklich benötigen, aber für den Fall, dass Sie sie benötigen, ist sie vorhanden.
## Einen `APIRouter` in einen anderen einfügen
## Einen `APIRouter` in einen anderen einfügen { #include-an-apirouter-in-another }
Auf die gleiche Weise, wie Sie einen `APIRouter` in eine `FastAPI`-Anwendung einbinden können, können Sie einen `APIRouter` in einen anderen `APIRouter` einbinden, indem Sie Folgendes verwenden:
+12 -12
View File
@@ -1,8 +1,8 @@
# Body – Felder
# Body – Felder { #body-fields }
So wie Sie zusätzliche Validation und Metadaten in Parametern der **Pfadoperation-Funktion** mittels `Query`, `Path` und `Body` deklarieren, können Sie auch innerhalb von Pydantic-Modellen zusätzliche Validation und Metadaten deklarieren, mittels Pydantics `Field`.
So wie Sie zusätzliche Validierung und Metadaten in Parametern der *Pfadoperation-Funktion* mittels `Query`, `Path` und `Body` deklarieren, können Sie auch innerhalb von Pydantic-Modellen zusätzliche Validierung und Metadaten deklarieren, mittels Pydantics `Field`.
## `Field` importieren
## `Field` importieren { #import-field }
Importieren Sie es zuerst:
@@ -14,7 +14,7 @@ Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fas
///
## Modellattribute deklarieren
## Modellattribute deklarieren { #declare-model-attributes }
Dann können Sie `Field` mit Modellattributen deklarieren:
@@ -24,23 +24,23 @@ Dann können Sie `Field` mit Modellattributen deklarieren:
/// 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.
Tatsächlich erstellen `Query`, `Path` und andere, die Sie als nächstes sehen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, welche selbst eine Unterklasse von Pydantics `FieldInfo`-Klasse ist.
Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück.
`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
`Body` gibt auch direkt Instanzen einer Unterklasse von `FieldInfo` zurück. Später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
Denken Sie daran, dass `Query`, `Path` und andere, wenn Sie sie von `fastapi` importieren, 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`.
Beachten Sie, wie jedes Attribut eines Modells 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
## Zusätzliche Information hinzufügen { #add-extra-information }
Sie können zusätzliche Information in `Field`, `Query`, `Body`, usw. deklarieren. Und es wird im generierten JSON-Schema untergebracht.
@@ -48,12 +48,12 @@ Sie werden später mehr darüber lernen, wie man zusätzliche Information unterb
/// 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.
Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel möglicherweise nicht 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
## Zusammenfassung { #recap }
Sie können Pydantics `Field` verwenden, um zusätzliche Validierungen und Metadaten für Modellattribute zu deklarieren.
Sie können auch Extra-Schlüssel verwenden, um zusätzliche JSON-Schema-Metadaten zu überreichen.
Sie können auch die zusätzlichen Schlüsselwortargumente verwenden, um zusätzliche JSON-Schema-Metadaten zu übergeben.
+24 -24
View File
@@ -1,8 +1,8 @@
# Body – Mehrere Parameter
# Body – Mehrere Parameter { #body-multiple-parameters }
Jetzt, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von Requestbody-Deklarationen an.
Nun, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von <abbr title="Anfragekörper">Requestbody</abbr>-Deklarationen an.
## `Path`-, `Query`- und Body-Parameter vermischen
## `Path`-, `Query`- und Body-Parameter vermischen { #mix-path-query-and-body-parameters }
Zuerst einmal, Sie können `Path`-, `Query`- und Requestbody-Parameter-Deklarationen frei mischen und **FastAPI** wird wissen, was zu tun ist.
@@ -16,9 +16,9 @@ Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, op
///
## Mehrere Body-Parameter
## Mehrere Body-Parameter { #multiple-body-parameters }
Im vorherigen Beispiel erwartete die *Pfadoperation* einen JSON-Body mit den Attributen eines `Item`s, etwa:
Im vorherigen Beispiel erwarteten die *Pfadoperationen* einen JSON-Body mit den Attributen eines `Item`s, etwa:
```JSON
{
@@ -35,7 +35,7 @@ Aber Sie können auch mehrere Body-Parameter deklarieren, z. B. `item` und `user
In diesem Fall wird **FastAPI** bemerken, dass es mehr als einen Body-Parameter in der Funktion gibt (zwei Parameter, die Pydantic-Modelle sind).
Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden, und erwartet einen Body wie folgt:
Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden und erwartet einen Body wie folgt:
```JSON
{
@@ -58,17 +58,17 @@ Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem
///
**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, genau so wie der Parameter `user`.
**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, und das Gleiche gilt für den Parameter `user`.
Es wird die Validierung dieser zusammengesetzten Daten übernehmen, und sie im OpenAPI-Schema und der automatischen Dokumentation dokumentieren.
Es wird die Validierung dieser zusammengesetzten Daten übernehmen, und diese im OpenAPI-Schema und der automatischen Dokumentation dokumentieren.
## Einzelne Werte im Body
## Einzelne Werte im Body { #singular-values-in-body }
So wie `Query` und `Path` für Query- und Pfad-Parameter, hat **FastAPI** auch das Äquivalent `Body`, um Extra-Daten für Body-Parameter zu definieren.
So wie `Query` und `Path` für Query- und Pfad-Parameter, stellt **FastAPI** das Äquivalent `Body` zur Verfügung, um Extra-Daten für Body-Parameter zu definieren.
Zum Beispiel, das vorherige Modell erweiternd, könnten Sie entscheiden, dass Sie einen weiteren Schlüssel <abbr title="Wichtigkeit">`importance`</abbr> haben möchten, im selben Body, Seite an Seite mit `item` und `user`.
Zum Beispiel, das vorherige Modell erweiternd, könnten Sie entscheiden, dass Sie einen weiteren Schlüssel `importance` im selben Body haben möchten, neben `item` und `user`.
Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, dass es ein Query-Parameter ist.
Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, dass es ein Query-Parameter ist, da er ein einzelner Wert ist.
Aber Sie können **FastAPI** instruieren, ihn als weiteren Body-Schlüssel zu erkennen, indem Sie `Body` verwenden:
@@ -92,9 +92,9 @@ In diesem Fall erwartet **FastAPI** einen Body wie:
}
```
Wiederum wird es die Daten konvertieren, validieren, dokumentieren, usw.
Wiederum wird es die Datentypen konvertieren, validieren, dokumentieren, usw.
## Mehrere Body-Parameter und Query-Parameter
## Mehrere Body-Parameter und Query-Parameter { #multiple-body-params-and-query }
Natürlich können Sie auch, wann immer Sie das brauchen, weitere Query-Parameter hinzufügen, zusätzlich zu den Body-Parametern.
@@ -112,21 +112,21 @@ q: str | None = None
Zum Beispiel:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[27] *}
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
/// info
/// info | Info
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen.
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query`, `Path` und andere, die Sie später kennenlernen werden.
///
## Einen einzelnen Body-Parameter einbetten
## Einen einzelnen Body-Parameter einbetten { #embed-a-single-body-parameter }
Nehmen wir an, Sie haben nur einen einzelnen `item`-Body-Parameter, ein Pydantic-Modell `Item`.
Nehmen wir an, Sie haben nur einen einzelnen `item`-Body-Parameter von einem Pydantic-Modell `Item`.
Normalerweise wird **FastAPI** dann seinen JSON-Body direkt erwarten.
Standardmäßig wird **FastAPI** dann seinen Body direkt erwarten.
Aber wenn Sie möchten, dass es einen JSON-Body erwartet, mit einem Schlüssel `item` und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen:
Aber wenn Sie möchten, dass es einen JSON-Body mit einem Schlüssel `item` erwartet, und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen:
```Python
item: Item = Body(embed=True)
@@ -160,11 +160,11 @@ statt:
}
```
## Zusammenfassung
## Zusammenfassung { #recap }
Sie können mehrere Body-Parameter zu ihrer *Pfadoperation-Funktion* hinzufügen, obwohl ein Request nur einen einzigen Body enthalten kann.
Sie können mehrere Body-Parameter zu Ihrer *Pfadoperation-Funktion* hinzufügen, obwohl ein Request nur einen einzigen Body enthalten kann.
**FastAPI** wird sich darum kümmern, Ihnen korrekte Daten in Ihrer Funktion zu überreichen, und das korrekte Schema in der *Pfadoperation* zu validieren und zu dokumentieren.
Aber **FastAPI** wird sich darum kümmern, Ihnen korrekte Daten in Ihrer Funktion zu überreichen, und das korrekte Schema in der *Pfadoperation* zu validieren und zu dokumentieren.
Sie können auch einzelne Werte deklarieren, die als Teil des Bodys empfangen werden.
+33 -33
View File
@@ -1,20 +1,20 @@
# Body – Verschachtelte Modelle
# Body – Verschachtelte Modelle { #body-nested-models }
Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle definieren, validieren und dokumentieren.
Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle definieren, validieren, dokumentieren und verwenden.
## Listen als Felder
## Listen als Felder { #list-fields }
Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`e.
Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`.
{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *}
Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der Elemente der Liste aussagt.
## Listen mit Typ-Parametern als Felder
## Listen mit Typ-Parametern als Felder { #list-fields-with-type-parameter }
Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren.
### `List` von `typing` importieren
### `List` von `typing` importieren { #import-typings-list }
In Python 3.9 oder darüber können Sie einfach `list` verwenden, um diese Typannotationen zu deklarieren, wie wir unten sehen werden. 💡
@@ -22,7 +22,7 @@ In Python-Versionen vor 3.9 (3.6 und darüber), müssen Sie zuerst `List` von Py
{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
### Eine `list`e mit einem Typ-Parameter deklarieren
### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter }
Um Typen wie `list`, `dict`, `tuple` mit inneren Typ-Parametern (inneren Typen) zu deklarieren:
@@ -51,7 +51,7 @@ In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Li
{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
## Set-Typen
## Set-Typen { #set-types }
Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollen, es sollen eindeutige Strings sein.
@@ -61,13 +61,13 @@ Deklarieren wir also `tags` als Set von Strings.
{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *}
Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert.
Jetzt, selbst wenn Sie einen <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert.
Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Dingen ausgegeben.
Und es wird entsprechend annotiert/dokumentiert.
## Verschachtelte Modelle
## Verschachtelte Modelle { #nested-models }
Jedes Attribut eines Pydantic-Modells hat einen Typ.
@@ -77,19 +77,19 @@ Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifi
Alles das beliebig tief verschachtelt.
### Ein Kindmodell definieren
### Ein Kindmodell definieren { #define-a-submodel }
Wir können zum Beispiel ein `Image`-Modell definieren.
Für ein Beispiel können wir ein `Image`-Modell definieren.
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
### Das Kindmodell als Typ verwenden
### Das Kindmodell als Typ verwenden { #use-the-submodel-as-a-type }
Und dann können wir es als Typ eines Attributes verwenden.
Und dann können wir es als Typ eines Attributes verwenden:
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *}
Das würde bedeuten, dass **FastAPI** einen Body erwartet wie:
Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet:
```JSON
{
@@ -112,25 +112,25 @@ Wiederum, nur mit dieser Deklaration erhalten Sie von **FastAPI**:
* Datenvalidierung
* Automatische Dokumentation
## Spezielle Typen und Validierungen
## Spezielle Typen und Validierungen { #special-types-and-validation }
Abgesehen von normalen einfachen Typen, wie `str`, `int`, `float`, usw. können Sie komplexere einfache Typen verwenden, die von `str` erben.
Abgesehen von normalen einfachen Typen wie `str`, `int`, `float`, usw. können Sie komplexere einfache Typen verwenden, die von `str` erben.
Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydantics Typübersicht</a> an. Sie werden im nächsten Kapitel ein paar Beispiele kennenlernen.
Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydantics Typübersicht</a> an. Sie werden einige Beispiele im nächsten Kapitel kennenlernen.
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`:
Zum Beispiel, da wir im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`:
{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *}
Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in JSON Schema / OpenAPI dokumentiert.
## Attribute mit Listen von Kindmodellen
## Attribute mit Listen von Kindmodellen { #attributes-with-lists-of-submodels }
Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden:
{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie:
Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren, usw.) wie:
```JSON hl_lines="11"
{
@@ -156,27 +156,27 @@ Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie
}
```
/// info
/// info | Info
Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat.
///
## Tief verschachtelte Modelle
## Tief verschachtelte Modelle { #deeply-nested-models }
Sie können beliebig tief verschachtelte Modelle definieren:
{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
/// info
/// info | Info
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat.
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben.
///
## Bodys aus reinen Listen
## Bodys aus reinen Listen { #bodies-of-pure-lists }
Wenn Sie möchten, dass das äußerste Element des JSON-Bodys ein JSON-`array` (eine Python-`list`e) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen:
Wenn das äußerste Element des JSON-Bodys, das Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen:
```Python
images: List[Image]
@@ -192,7 +192,7 @@ so wie in:
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
## Editor-Unterstützung überall
## Editor-Unterstützung überall { #editor-support-everywhere }
Und Sie erhalten Editor-Unterstützung überall.
@@ -204,11 +204,11 @@ Sie würden diese Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dic
Aber Sie müssen sich auch nicht weiter um die Modelle kümmern, hereinkommende Dicts werden automatisch in sie konvertiert. Und was Sie zurückgeben, wird automatisch nach JSON konvertiert.
## Bodys mit beliebigen `dict`s
## Bodys mit beliebigen `dict`s { #bodies-of-arbitrary-dicts }
Sie können einen Body auch als `dict` deklarieren, mit Schlüsseln eines Typs und Werten eines anderen Typs.
So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attribut-Namen lauten (wie es bei Pydantic-Modellen der Fall wäre).
So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre).
Das ist nützlich, wenn Sie Schlüssel empfangen, deren Namen Sie nicht bereits kennen.
@@ -218,7 +218,7 @@ Ein anderer nützlicher Anwendungsfall ist, wenn Sie Schlüssel eines anderen Ty
Das schauen wir uns mal an.
Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat.
Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat:
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
@@ -230,11 +230,11 @@ 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.
Und das `dict`, welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben.
///
## Zusammenfassung
## Zusammenfassung { #recap }
Mit **FastAPI** haben Sie die maximale Flexibilität von Pydantic-Modellen, während Ihr Code einfach, kurz und elegant bleibt.
+19 -19
View File
@@ -1,16 +1,16 @@
# Body – Aktualisierungen
# Body – Aktualisierungen { #body-updates }
## Ersetzendes Aktualisieren mit `PUT`
## Ersetzendes Aktualisieren mit `PUT` { #update-replacing-with-put }
Um einen Artikel zu aktualisieren, können Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> Operation verwenden.
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.
Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (z. B. in einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren.
{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
`PUT` wird verwendet, um Daten zu empfangen, die die existierenden Daten ersetzen sollen.
### Warnung bezüglich des Ersetzens
### Warnung bezüglich des Ersetzens { #warning-about-replacing }
Das bedeutet, dass, wenn Sie den Artikel `bar` aktualisieren wollen, mittels `PUT` und folgendem Body:
@@ -22,15 +22,15 @@ Das bedeutet, dass, wenn Sie den Artikel `bar` aktualisieren wollen, mittels `PU
}
```
das Eingabemodell nun den Defaultwert `"tax": 10.5` hat, weil Sie das bereits gespeicherte Attribut `"tax": 20.2` nicht mit übergeben haben.
weil das bereits gespeicherte Attribut `"tax": 20.2` nicht enthalten ist, das Eingabemodell den Defaultwert `"tax": 10.5` erhalten würde.
Die Daten werden darum mit einem „neuen“ `tax`-Wert von `10.5` abgespeichert.
Und die Daten würden mit diesem „neuen“ `tax` von `10.5` gespeichert werden.
## Teilweises Ersetzen mit `PATCH`
## Teil-Aktualisierungen mit `PATCH` { #partial-updates-with-patch }
Sie können auch die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> Operation verwenden, um Daten *teilweise* zu ersetzen.
Das bedeutet, sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert.
Das bedeutet, Sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert.
/// note | Hinweis
@@ -44,33 +44,33 @@ Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweis
///
### Pydantics `exclude_unset`-Parameter verwenden
### Pydantics `exclude_unset`-Parameter verwenden { #using-pydantics-exclude-unset-parameter }
Wenn Sie Teil-Aktualisierungen entgegennehmen, ist der `exclude_unset`-Parameter in der `.model_dump()`-Methode von Pydantic-Modellen sehr nützlich.
Wie in `item.model_dump(exclude_unset=True)`.
/// info
/// info | Info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> (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.
Das wird ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> 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:
Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr>) gesendeten Daten enthält, ohne Defaultwerte:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
### Pydantics `update`-Parameter verwenden
### Pydantics `update`-Parameter verwenden { #using-pydantics-update-parameter }
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
/// info | Info
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt.
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> (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.
@@ -80,9 +80,9 @@ Wie in `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
### Rekapitulation zum teilweisen Ersetzen
### Rekapitulation zu Teil-Aktualisierungen { #partial-updates-recap }
Zusammengefasst, um Teil-Ersetzungen vorzunehmen:
Zusammengefasst, um Teil-Aktualisierungen vorzunehmen:
* (Optional) verwenden Sie `PATCH` statt `PUT`.
* Lesen Sie die bereits gespeicherten Daten aus.
@@ -90,7 +90,7 @@ Zusammengefasst, um Teil-Ersetzungen vorzunehmen:
* Erzeugen Sie aus dem empfangenen Modell ein `dict` ohne Defaultwerte (mittels `exclude_unset`).
* So ersetzen Sie nur die tatsächlich vom Benutzer gesetzten Werte, statt dass bereits gespeicherte Werte mit Defaultwerten des Modells überschrieben werden.
* Erzeugen Sie eine Kopie ihres gespeicherten Modells, wobei Sie die Attribute mit den empfangenen Teil-Ersetzungen aktualisieren (mittels des `update`-Parameters).
* Konvertieren Sie das kopierte Modell zu etwas, das in ihrer Datenbank gespeichert werden kann (indem Sie beispielsweise `jsonable_encoder` verwenden).
* Konvertieren Sie das kopierte Modell zu etwas, das in Ihrer Datenbank gespeichert werden kann (indem Sie beispielsweise `jsonable_encoder` verwenden).
* Das ist vergleichbar dazu, die `.model_dump()`-Methode des Modells erneut aufzurufen, aber es wird sicherstellen, dass die Werte zu Daten konvertiert werden, die ihrerseits zu JSON konvertiert werden können, zum Beispiel `datetime` zu `str`.
* Speichern Sie die Daten in Ihrer Datenbank.
* Geben Sie das aktualisierte Modell zurück.
+58 -47
View File
@@ -1,40 +1,40 @@
# Requestbody
# Requestbody { #request-body }
Wenn Sie Daten von einem <abbr title="Client: Eine Software, die sich mit einem Server verbindet.">Client</abbr> (sagen wir, einem Browser) zu Ihrer API senden, dann senden Sie diese als einen **Requestbody** (Deutsch: Anfragekörper).
Wenn Sie Daten von einem <abbr title="Client: Eine Software, die sich mit einem Server verbindet.">Client</abbr> (sagen wir, einem Browser) zu Ihrer API senden müssen, senden Sie sie als **Requestbody**.
Ein **Request**body sind Daten, die vom Client zu Ihrer API gesendet werden. Ein **Response**body (Deutsch: Antwortkörper) sind Daten, die Ihre API zum Client sendet.
Ein <abbr title="Anfragekörper">**Request**body</abbr> sind Daten, die vom Client zu Ihrer API gesendet werden. Ein <abbr title="Antwortkörper">**Response**body</abbr> sind Daten, die Ihre API zum Client sendet.
Ihre API sendet fast immer einen **Response**body. Aber Clients senden nicht unbedingt immer **Request**bodys (sondern nur Metadaten).
Ihre API muss fast immer einen **Response**body senden. Aber Clients müssen nicht unbedingt immer **Requestbodys** senden, manchmal fordern sie nur einen Pfad an, vielleicht mit einigen Query-Parametern, aber senden keinen Body.
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.
Um einen **Request**body zu deklarieren, verwenden Sie <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>-Modelle mit all deren Fähigkeiten und Vorzügen.
/// info
/// info | Info
Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
Um Daten zu senden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
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.
Das Senden eines Bodys mit einem `GET`-Request hat ein undefiniertes Verhalten in den Spezifikationen, wird aber dennoch von FastAPI unterstützt, nur 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.
Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht.
///
## Importieren Sie Pydantics `BaseModel`
## Pydantics `BaseModel` importieren { #import-pydantics-basemodel }
Zuerst müssen Sie `BaseModel` von `pydantic` importieren:
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
## Erstellen Sie Ihr Datenmodell
## Ihr Datenmodell erstellen { #create-your-data-model }
Dann deklarieren Sie Ihr Datenmodell als eine Klasse, die von `BaseModel` erbt.
Verwenden Sie Standard-Python-Typen für die Klassenattribute:
Verwenden Sie Standard-Python-Typen für alle Attribute:
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
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.
Wie auch bei der Deklaration von Query-Parametern gilt: Wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Andernfalls ist es erforderlich. Verwenden Sie `None`, um es einfach optional zu machen.
Zum Beispiel deklariert das obige Modell ein JSON "`object`" (oder Python-`dict`) wie dieses:
Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-<abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr>) wie dieses:
```JSON
{
@@ -45,7 +45,7 @@ Zum Beispiel deklariert das obige Modell ein JSON "`object`" (oder Python-`dict`
}
```
Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre folgendes JSON "`object`" auch gültig:
Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre folgendes JSON „`object`“ auch gültig:
```JSON
{
@@ -54,109 +54,120 @@ Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre fol
}
```
## Deklarieren Sie es als Parameter
## Als Parameter deklarieren { #declare-it-as-a-parameter }
Um es zu Ihrer *Pfadoperation* hinzuzufügen, deklarieren Sie es auf die gleiche Weise, wie Sie Pfad- und Query-Parameter deklariert haben:
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
... und deklarieren Sie seinen Typ als das Modell, welches Sie erstellt haben, `Item`.
... und deklarieren Sie dessen Typ als das Modell, welches Sie erstellt haben, `Item`.
## Resultate
## Resultate { #results }
Mit nur dieser Python-Typdeklaration, wird **FastAPI**:
Mit nur dieser Python-Typdeklaration wird **FastAPI**:
* Den Requestbody als JSON lesen.
* Die entsprechenden Typen konvertieren (falls nötig).
* Diese Daten validieren.
* Wenn die Daten ungültig sind, einen klar lesbaren Fehler zurückgeben, der anzeigt, wo und was die inkorrekten Daten waren.
* Wenn die Daten ungültig sind, wird ein klar lesbarer Fehler zurückgegeben, der genau anzeigt, wo und was die inkorrekten Daten sind.
* Ihnen die erhaltenen Daten im Parameter `item` übergeben.
* Da Sie diesen in der Funktion als vom Typ `Item` deklariert haben, erhalten Sie die ganze Editor-Unterstützung (Autovervollständigung, usw.) für alle Attribute und deren Typen.
* Eine <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> Definition für Ihr Modell generieren, welche Sie überall sonst verwenden können, wenn es für Ihr Projekt Sinn macht.
* Diese Schemas werden Teil des generierten OpenAPI-Schemas und werden von den <abbr title="User Interface – Benutzeroberfläche">UIs</abbr> der automatischen Dokumentation verwendet.
* Da Sie ihn in der Funktion als vom Typ `Item` deklariert haben, erhalten Sie auch die volle Unterstützung des Editors (Autovervollständigung, usw.) für alle Attribute und deren Typen.
* <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a>-Definitionen für Ihr Modell generieren, die Sie auch überall sonst verwenden können, wenn es für Ihr Projekt Sinn macht.
* Diese Schemas werden Teil des generierten OpenAPI-Schemas und werden von den <abbr title="User Interfaces – Benutzeroberflächen">UIs</abbr> der automatischen Dokumentation genutzt.
## Automatische Dokumentation
## Automatische Dokumentation { #automatic-docs }
Die JSON-Schemas Ihrer Modelle werden Teil ihrer OpenAPI-generierten Schemas und werden in der interaktiven API Dokumentation angezeigt:
Die JSON-Schemas Ihrer Modelle werden Teil Ihres OpenAPI-generierten Schemas und in der interaktiven API-Dokumentation angezeigt:
<img src="/img/tutorial/body/image01.png">
Und werden auch verwendet in der API-Dokumentation innerhalb jeder *Pfadoperation*, welche sie braucht:
Und werden auch in der API-Dokumentation innerhalb jeder *Pfadoperation*, die sie benötigt, verwendet:
<img src="/img/tutorial/body/image02.png">
## Editor Unterstützung
## Editor-Unterstützung { #editor-support }
In Ihrem Editor, innerhalb Ihrer Funktion, erhalten Sie Typhinweise und Code-Vervollständigung überall (was nicht der Fall wäre, wenn Sie ein `dict` anstelle eines Pydantic Modells erhalten hätten):
In Ihrem Editor erhalten Sie innerhalb Ihrer Funktion Typhinweise und Code-Vervollständigung überall (was nicht der Fall wäre, wenn Sie ein `dict` anstelle eines Pydantic-Modells erhalten hätten):
<img src="/img/tutorial/body/image03.png">
Sie bekommen auch Fehler-Meldungen für inkorrekte Typoperationen:
Sie bekommen auch Fehlermeldungen für inkorrekte Typoperationen:
<img src="/img/tutorial/body/image04.png">
Das ist nicht zufällig so, das ganze Framework wurde um dieses Design herum aufgebaut.
Und es wurde in der Designphase gründlich getestet, vor der Implementierung, um sicherzustellen, dass es mit jedem Editor funktioniert.
Und es wurde in der Designphase gründlich getestet, bevor irgendeine Implementierung stattfand, um sicherzustellen, dass es mit allen Editoren funktioniert.
Es gab sogar ein paar Änderungen an Pydantic selbst, um das zu unterstützen.
Es gab sogar einige Änderungen an Pydantic selbst, um dies zu unterstützen.
Die vorherigen Screenshots zeigten <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>.
Die vorherigen Screenshots wurden mit <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a> aufgenommen.
Aber Sie bekommen die gleiche Editor-Unterstützung in <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> und in den meisten anderen Python-Editoren:
Aber Sie würden die gleiche Editor-Unterstützung in <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> und den meisten anderen Python-Editoren erhalten:
<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.
Wenn Sie <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> als Ihren Editor verwenden, können Sie das <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> ausprobieren.
Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit:
* Code-Vervollständigung
* Typüberprüfungen
* Refaktorisierung
* Suchen
* Suche
* Inspektionen
///
## Das Modell verwenden
## Das Modell verwenden { #use-the-model }
Innerhalb der Funktion können Sie alle Attribute des Modells direkt verwenden:
Innerhalb der Funktion können Sie alle Attribute des Modellobjekts direkt verwenden:
{* ../../docs_src/body/tutorial002_py310.py hl[19] *}
{* ../../docs_src/body/tutorial002_py310.py *}
## Requestbody- + Pfad-Parameter
/// info | Info
Sie können Pfad- und Requestbody-Parameter gleichzeitig deklarieren.
In Pydantic v1 hieß die Methode `.dict()`, sie wurde in Pydantic v2 deprecatet (aber weiterhin unterstützt) und in `.model_dump()` umbenannt.
Die Beispiele hier verwenden `.dict()` zur Kompatibilität mit Pydantic v1, aber Sie sollten stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 nutzen können.
///
## Requestbody- + Pfad-Parameter { #request-body-path-parameters }
Sie können Pfad-Parameter und den Requestbody 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.
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
## Requestbody- + Pfad- + Query-Parameter
## Requestbody- + Pfad- + Query-Parameter { #request-body-path-query-parameters }
Sie können auch zur gleichen Zeit **Body-**, **Pfad-** und **Query-Parameter** deklarieren.
**FastAPI** wird jeden Parameter korrekt erkennen und die Daten vom richtigen Ort holen.
**FastAPI** wird jeden von ihnen korrekt erkennen und die Daten vom richtigen Ort holen.
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
Die Funktionsparameter werden wie folgt erkannt:
* Wenn der Parameter auch im **Pfad** deklariert wurde, wird er als Pfad-Parameter interpretiert.
* Wenn der Parameter auch im **Pfad** deklariert wurde, wird er als Pfad-Parameter verwendet.
* 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`
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, aufgrund 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.
Das `str | None` (Python 3.10+) oder `Union` in `Union[str, None]` (Python 3.8+) wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiß, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat.
Das Hinzufügen der Typannotationen ermöglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstützung zu bieten und Fehler zu erkennen.
///
## Ohne Pydantic
## Ohne Pydantic { #without-pydantic }
Wenn Sie keine Pydantic-Modelle verwenden wollen, können Sie auch **Body**-Parameter nehmen. Siehe die Dokumentation unter [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#einzelne-werte-im-body){.internal-link target=\_blank}.
Wenn Sie keine Pydantic-Modelle verwenden möchten, können Sie auch **Body**-Parameter verwenden. Siehe die Dokumentation unter [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
@@ -0,0 +1,76 @@
# Cookie-Parameter-Modelle { #cookie-parameter-models }
Wenn Sie eine Gruppe von **Cookies** haben, die zusammengehören, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. 🍪
Damit können Sie das Modell an **mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎
/// note | Hinweis
Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓
///
/// tip | Tipp
Diese gleiche Technik gilt für `Query`, `Cookie` und `Header`. 😎
///
## Cookies mit einem Pydantic-Modell { #cookies-with-a-pydantic-model }
Deklarieren Sie die **Cookie**-Parameter, die Sie benötigen, in einem **Pydantic-Modell**, und deklarieren Sie dann den Parameter als `Cookie`:
{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
**FastAPI** wird die Daten für **jedes Feld** aus den im <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> empfangenen **Cookies** **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell bereitstellen.
## Die Dokumentation testen { #check-the-docs }
Sie können die definierten Cookies in der Dokumentationsoberfläche unter `/docs` sehen:
<div class="screenshot">
<img src="/img/tutorial/cookie-param-models/image01.png">
</div>
/// info | Info
Bitte beachten Sie, dass Browser Cookies auf spezielle Weise und im Hintergrund bearbeiten, sodass sie **nicht** leicht **JavaScript** erlauben, diese zu berühren.
Wenn Sie zur **API-Dokumentationsoberfläche** unter `/docs` gehen, können Sie die **Dokumentation** für Cookies für Ihre *Pfadoperationen* sehen.
Aber selbst wenn Sie die **Daten ausfüllen** und auf „Ausführen“ klicken, werden aufgrund der Tatsache, dass die Dokumentationsoberfläche mit **JavaScript** arbeitet, die Cookies nicht gesendet, und Sie werden eine **Fehlermeldung** sehen, als ob Sie keine Werte eingegeben hätten.
///
## Zusätzliche Cookies verbieten { #forbid-extra-cookies }
In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Cookies, die Sie empfangen möchten, **einschränken**.
Ihre API hat jetzt die Macht, ihre eigene <abbr title="Das ist ein Scherz, nur für den Fall. Es hat nichts mit Cookie-Einwilligungen zu tun, aber es ist witzig, dass selbst die API jetzt die armen Cookies ablehnen kann. Haben Sie einen Keks. 🍪">Cookie-Einwilligung</abbr> zu kontrollieren. 🤪🍪
Sie können die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`):
{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
Wenn ein Client versucht, einige **zusätzliche Cookies** zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
Arme Cookie-Banner, wie sie sich mühen, Ihre Einwilligung zu erhalten, dass die <abbr title="Das ist ein weiterer Scherz. Beachten Sie mich nicht. Trinken Sie einen Kaffee zu Ihrem Keks. ☕">API sie ablehnen darf</abbr>. 🍪
Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem Wert von `good-list-please` zu senden, erhält der Client eine **Error-Response**, die ihm mitteilt, dass das `santa_tracker` <abbr title="Santa beschwert sich über den Mangel an Cookies. 🎅 Okay, keine Cookie-Witze mehr.">Cookie nicht erlaubt ist</abbr>:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["cookie", "santa_tracker"],
"msg": "Extra inputs are not permitted",
"input": "good-list-please",
}
]
}
```
## Zusammenfassung { #summary }
Sie können **Pydantic-Modelle** verwenden, um <abbr title="Nehmen Sie einen letzten Keks, bevor Sie gehen. 🍪">**Cookies**</abbr> in **FastAPI** zu deklarieren. 😎
+12 -12
View File
@@ -1,35 +1,35 @@
# Cookie-Parameter
# Cookie-Parameter { #cookie-parameters }
So wie `Query`- und `Path`-Parameter können Sie auch <abbr title='Cookie – „Keks“: Mechanismus, der kurze Daten in Textform im Browser des Benutzers speichert und abfragt'>Cookie</abbr>-Parameter definieren.
Sie können Cookie-Parameter auf die gleiche Weise definieren wie `Query`- und `Path`-Parameter.
## `Cookie` importieren
## `Cookie` importieren { #import-cookie }
Importieren Sie zuerst `Cookie`:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
## `Cookie`-Parameter deklarieren
## `Cookie`-Parameter deklarieren { #declare-cookie-parameters }
Dann deklarieren Sie Ihre Cookie-Parameter, auf die gleiche Weise, wie Sie auch `Path`- und `Query`-Parameter deklarieren.
Deklarieren Sie dann die Cookie-Parameter mit derselben Struktur wie bei `Path` und `Query`.
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:
Sie können den Defaultwert sowie alle zusätzlichen Validierungen oder Annotierungsparameter definieren:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
/// note | Technische Details
`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
`Cookie` ist eine „Schwester“-Klasse von `Path` und `Query`. Sie erbt auch von derselben gemeinsamen `Param`-Klasse.
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.
Aber denken Sie daran, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
///
/// info
/// info | Info
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sonst als Query-Parameter interpretiert würden.
///
## Zusammenfassung
## Zusammenfassung { #recap }
Deklarieren Sie Cookies mittels `Cookie`, auf die gleiche Weise wie bei `Query` und `Path`.
Deklarieren Sie Cookies mit `Cookie` und verwenden Sie dabei das gleiche allgemeine Muster wie bei `Query` und `Path`.
+88
View File
@@ -0,0 +1,88 @@
# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing }
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS oder <abbr title="Ressourcenfreigabe zwischen Ursprüngen">„Cross-Origin Resource Sharing“</abbr></a> bezieht sich auf Situationen, in denen ein Frontend, das in einem Browser läuft, JavaScript-Code enthält, der mit einem Backend kommuniziert, und das Backend sich in einem anderen „Origin“ als das Frontend befindet.
## Origin { #origin }
Ein <abbr title="Ursprung">Origin</abbr> ist die Kombination aus Protokoll (`http`, `https`), Domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`) und Port (`80`, `443`, `8080`).
Alle folgenden sind also unterschiedliche Origins:
* `http://localhost`
* `https://localhost`
* `http://localhost:8080`
Auch wenn sie alle in `localhost` sind, verwenden sie unterschiedliche Protokolle oder Ports, daher sind sie unterschiedliche „Origins“.
## Schritte { #steps }
Angenommen, Sie haben ein Frontend, das in Ihrem Browser unter `http://localhost:8080` läuft, und dessen JavaScript versucht, mit einem Backend zu kommunizieren, das unter `http://localhost` läuft (da wir keinen Port angegeben haben, geht der Browser vom Default-Port `80` aus).
Dann wird der Browser ein HTTP-`OPTIONS`-<abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> an das `:80`-Backend senden, und wenn das Backend die entsprechenden Header sendet, die die Kommunikation von diesem anderen Origin (`http://localhost:8080`) autorisieren, lässt der `:8080`-Browser das JavaScript im Frontend seinen Request an das `:80`-Backend senden.
Um dies zu erreichen, muss das `:80`-Backend eine Liste von „erlaubten Origins“ haben.
In diesem Fall müsste die Liste `http://localhost:8080` enthalten, damit das `:8080`-Frontend korrekt funktioniert.
## Wildcards { #wildcards }
Es ist auch möglich, die Liste als `"*"` (ein „Wildcard“) zu deklarieren, um anzuzeigen, dass alle erlaubt sind.
Aber das erlaubt nur bestimmte Arten der Kommunikation und schließt alles aus, was Anmeldeinformationen beinhaltet: Cookies, Autorisierungsheader wie die, die mit Bearer Tokens verwendet werden, usw.
Um sicherzustellen, dass alles korrekt funktioniert, ist es besser, die erlaubten Origins explizit anzugeben.
## `CORSMiddleware` verwenden { #use-corsmiddleware }
Sie können das in Ihrer **FastAPI**-Anwendung mit der `CORSMiddleware` konfigurieren.
* Importieren Sie `CORSMiddleware`.
* Erstellen Sie eine Liste der erlaubten Origins (als Strings).
* Fügen Sie es als „Middleware“ zu Ihrer **FastAPI**-Anwendung hinzu.
Sie können auch angeben, ob Ihr Backend erlaubt:
* Anmeldeinformationen (Autorisierungsheader, Cookies, usw.).
* Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`.
* Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`.
{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmäßig restriktiv, daher müssen Sie bestimmte Origins, Methoden oder Header ausdrücklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dürfen.
Die folgenden Argumente werden unterstützt:
* `allow_origins` – Eine Liste von Origins, die Cross-Origin-Requests machen dürfen. z. B. `['https://example.org', 'https://www.example.org']`. Sie können `['*']` verwenden, um jedes Origin zuzulassen.
* `allow_origin_regex` – Ein Regex-String zum Abgleichen gegen Origins, die Cross-Origin-Requests machen dürfen. z. B. `'https://.*\.example\.org'`.
* `allow_methods` – Eine Liste von HTTP-Methoden, die für Cross-Origin-Requests erlaubt sein sollen. Standardmäßig `['GET']`. Sie können `['*']` verwenden, um alle Standardmethoden zu erlauben.
* `allow_headers` – Eine Liste von HTTP-Requestheadern, die für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `[]`. Sie können `['*']` verwenden, um alle Header zu erlauben. Die Header `Accept`, `Accept-Language`, `Content-Language` und `Content-Type` sind immer für <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">einfache CORS-Requests</a> erlaubt.
* `allow_credentials` – Anzeigen, dass Cookies für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `False`.
Keines der `allow_origins`, `allow_methods` und `allow_headers` kann auf `['*']` gesetzt werden, wenn `allow_credentials` auf `True` gesetzt ist. Alle müssen <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards" class="external-link" rel="noopener" target="_blank">explizit angegeben</a> werden.
* `expose_headers` – Angabe der Responseheader, auf die der Browser zugreifen können soll. Standardmäßig `[]`.
* `max_age` – Legt eine maximale Zeit in Sekunden fest, die Browser CORS-Responses zwischenspeichern dürfen. Standardmäßig `600`.
Die Middleware antwortet auf zwei besondere Arten von HTTP-Requests ...
### CORS-Preflight-Requests { #cors-preflight-requests }
Dies sind alle `OPTIONS`-Requests mit `Origin`- und `Access-Control-Request-Method`-Headern.
In diesem Fall wird die Middleware den eingehenden Request abfangen und mit entsprechenden CORS-Headern, und entweder einer `200`- oder `400`-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> zu Informationszwecken antworten.
### Einfache Requests { #simple-requests }
Jeder Request mit einem `Origin`-Header. In diesem Fall wird die Middleware den Request wie gewohnt durchlassen, aber entsprechende CORS-Header in die Response aufnehmen.
## Weitere Informationen { #more-info }
Weitere Informationen zu <abbr title="Cross-Origin Resource Sharing – Ressourcenfreigabe zwischen Ursprüngen">CORS</abbr> finden Sie in der <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS-Dokumentation</a>.
/// note | Technische Details
Sie könnten auch `from starlette.middleware.cors import CORSMiddleware` verwenden.
**FastAPI** bietet mehrere Middlewares in `fastapi.middleware` nur als Komfort für Sie, den Entwickler. Aber die meisten der verfügbaren Middlewares stammen direkt von Starlette.
///
+113
View File
@@ -0,0 +1,113 @@
# Debugging { #debugging }
Sie können den Debugger in Ihrem Editor verbinden, zum Beispiel mit Visual Studio Code oder PyCharm.
## `uvicorn` aufrufen { #call-uvicorn }
Importieren und führen Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus:
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
### Über `__name__ == "__main__"` { #about-name-main }
Der Hauptzweck von `__name__ == "__main__"` ist, dass Code ausgeführt wird, wenn Ihre Datei mit folgendem Befehl aufgerufen wird:
<div class="termy">
```console
$ python myapp.py
```
</div>
aber nicht aufgerufen wird, wenn eine andere Datei sie importiert, wie in:
```Python
from myapp import app
```
#### Weitere Details { #more-details }
Angenommen, Ihre Datei heißt `myapp.py`.
Wenn Sie sie mit folgendem Befehl ausführen:
<div class="termy">
```console
$ python myapp.py
```
</div>
dann hat in Ihrer Datei die interne Variable `__name__`, die von Python automatisch erstellt wird, als Wert den String `"__main__"`.
Daher wird der Abschnitt:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
ausgeführt.
---
Dies wird nicht passieren, wenn Sie das Modul (die Datei) importieren.
Wenn Sie also eine weitere Datei `importer.py` mit folgendem Inhalt haben:
```Python
from myapp import app
# Hier mehr Code
```
wird in diesem Fall in `myapp.py` die automatisch erstellte Variable `__name__` nicht den Wert `"__main__"` haben.
Daher wird die Zeile:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
nicht ausgeführt.
/// info | Info
Für weitere Informationen besuchen Sie bitte <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">die offizielle Python-Dokumentation</a>.
///
## Ihren Code mit Ihrem Debugger ausführen { #run-your-code-with-your-debugger }
Da Sie den Uvicorn-Server direkt aus Ihrem Code ausführen, können Sie Ihr Python-Programm (Ihre FastAPI-Anwendung) direkt aus dem Debugger aufrufen.
---
Zum Beispiel können Sie in Visual Studio Code:
* Zum „Debug“-Panel gehen.
* „Konfiguration hinzufügen ...“ auswählen.
* „Python“ auswählen.
* Den Debugger mit der Option „`Python: Current File (Integrated Terminal)`“ ausführen.
Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw.
So könnte es aussehen:
<img src="/img/tutorial/debugging/image01.png">
---
Wenn Sie Pycharm verwenden, können Sie:
* Das Menü „Run“ öffnen.
* Die Option „Debug ...“ auswählen.
* Ein Kontextmenü wird angezeigt.
* Die zu debuggende Datei auswählen (in diesem Fall `main.py`).
Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw.
So könnte es aussehen:
<img src="/img/tutorial/debugging/image02.png">
@@ -1,10 +1,10 @@
# Klassen als Abhängigkeiten
# Klassen als Abhängigkeiten { #classes-as-dependencies }
Bevor wir tiefer in das **Dependency Injection** System eintauchen, lassen Sie uns das vorherige Beispiel verbessern.
## Ein `dict` aus dem vorherigen Beispiel
## Ein `dict` aus dem vorherigen Beispiel { #a-dict-from-the-previous-example }
Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben:
Im vorherigen Beispiel haben wir ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> von unserer Abhängigkeit („Dependable“) zurückgegeben:
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *}
@@ -14,7 +14,7 @@ Und wir wissen, dass Editoren nicht viel Unterstützung (wie etwa Code-Vervollst
Das können wir besser machen ...
## Was macht eine Abhängigkeit aus
## Was macht eine Abhängigkeit aus { #what-makes-a-dependency }
Bisher haben Sie Abhängigkeiten gesehen, die als Funktionen deklariert wurden.
@@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo")
dann ist das ein „Callable“ (ein „Aufrufbares“).
## Klassen als Abhängigkeiten
## Klassen als Abhängigkeiten { #classes-as-dependencies_1 }
Möglicherweise stellen Sie fest, dass Sie zum Erstellen einer Instanz einer Python-Klasse die gleiche Syntax verwenden.
@@ -89,7 +89,7 @@ In beiden Fällen wird sie haben:
In beiden Fällen werden die Daten konvertiert, validiert, im OpenAPI-Schema dokumentiert, usw.
## Verwendung
## Verwenden { #use-it }
Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
@@ -97,7 +97,7 @@ Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
**FastAPI** ruft die Klasse `CommonQueryParams` auf. Dadurch wird eine „Instanz“ dieser Klasse erstellt und die Instanz wird als Parameter `commons` an Ihre Funktion überreicht.
## Typannotation vs. `Depends`
## Typannotation vs. `Depends` { #type-annotation-vs-depends }
Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben:
@@ -193,7 +193,7 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was al
<img src="/img/tutorial/dependencies/image02.png">
## Abkürzung
## Abkürzung { #shortcut }
Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben:
@@ -1,14 +1,14 @@
# Abhängigkeiten in Pfadoperation-Dekoratoren
# Abhängigkeiten in Pfadoperation-Dekoratoren { #dependencies-in-path-operation-decorators }
Manchmal benötigen Sie den Rückgabewert einer Abhängigkeit innerhalb Ihrer *Pfadoperation-Funktion* nicht wirklich.
Oder die Abhängigkeit gibt keinen Wert zurück.
Aber Sie müssen Sie trotzdem ausführen/auflösen.
Aber Sie müssen sie trotzdem ausführen/auflösen.
In diesen Fällen können Sie, anstatt einen Parameter der *Pfadoperation-Funktion* mit `Depends` zu deklarieren, eine `list`e von `dependencies` zum *Pfadoperation-Dekorator* hinzufügen.
## `dependencies` zum *Pfadoperation-Dekorator* hinzufügen
## `dependencies` zum *Pfadoperation-Dekorator* hinzufügen { #add-dependencies-to-the-path-operation-decorator }
Der *Pfadoperation-Dekorator* erhält ein optionales Argument `dependencies`.
@@ -28,7 +28,7 @@ Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die ein
///
/// info
/// info | Info
In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`.
@@ -36,23 +36,23 @@ Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr V
///
## Abhängigkeitsfehler und -Rückgabewerte
## Abhängigkeitsfehler und -Rückgabewerte { #dependencies-errors-and-return-values }
Sie können dieselben Abhängigkeits-*Funktionen* verwenden, die Sie normalerweise verwenden.
### Abhängigkeitsanforderungen
### Abhängigkeitsanforderungen { #dependency-requirements }
Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren:
Sie können Anforderungen für einen <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> (wie Header) oder andere Unterabhängigkeiten deklarieren:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
### Exceptions auslösen
### Exceptions auslösen { #raise-exceptions }
Die Abhängigkeiten können Exceptions `raise`n, genau wie normale Abhängigkeiten:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
### Rückgabewerte
### Rückgabewerte { #return-values }
Und sie können Werte zurückgeben oder nicht, die Werte werden nicht verwendet.
@@ -60,10 +60,10 @@ Sie können also eine normale Abhängigkeit (die einen Wert zurückgibt), die Si
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
## Abhängigkeiten für eine Gruppe von *Pfadoperationen*
## Abhängigkeiten für eine Gruppe von *Pfadoperationen* { #dependencies-for-a-group-of-path-operations }
Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Größere Anwendungen – Mehrere Dateien](../../tutorial/bigger-applications.md){.internal-link target=_blank}), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren.
## Globale Abhängigkeiten
## Globale Abhängigkeiten { #global-dependencies }
Als Nächstes werden wir sehen, wie man Abhängigkeiten zur gesamten `FastAPI`-Anwendung hinzufügt, sodass sie für jede *Pfadoperation* gelten.
@@ -1,4 +1,4 @@
# Abhängigkeiten mit yield
# Abhängigkeiten mit `yield` { #dependencies-with-yield }
FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige <abbr title="Manchmal auch genannt „Exit Code“, „Cleanup Code“, „Teardown Code“, „Closing Code“, „Kontext Manager Exit Code“, usw.">zusätzliche Schritte ausführen</abbr>.
@@ -23,11 +23,11 @@ Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern.
///
## Eine Datenbank-Abhängigkeit mit `yield`.
## Eine Datenbank-Abhängigkeit mit `yield` { #a-database-dependency-with-yield }
Sie könnten damit beispielsweise eine Datenbanksession erstellen und diese nach Abschluss schließen.
Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine Response erzeugt wird:
Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> erzeugt wird:
{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *}
@@ -35,19 +35,19 @@ Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeit
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Response gesendet wurde:
Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Response erstellt wurde, aber bevor sie gesendet wird:
{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
/// tip | Tipp
Sie können `async`hrone oder reguläre Funktionen verwenden.
Sie können `async`- 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`.
## Eine Abhängigkeit mit `yield` und `try` { #a-dependency-with-yield-and-try }
Wenn Sie einen `try`-Block in einer Abhängigkeit mit `yield` verwenden, empfangen Sie alle Exceptions, die bei Verwendung der Abhängigkeit geworfen wurden.
@@ -59,7 +59,7 @@ Auf die gleiche Weise können Sie `finally` verwenden, um sicherzustellen, dass
{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
## Unterabhängigkeiten mit `yield`.
## Unterabhängigkeiten mit `yield` { #sub-dependencies-with-yield }
Sie können Unterabhängigkeiten und „Bäume“ von Unterabhängigkeiten beliebiger Größe und Form haben, und einige oder alle davon können `yield` verwenden.
@@ -93,7 +93,7 @@ Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/cont
///
## Abhängigkeiten mit `yield` und `HTTPException`.
## Abhängigkeiten mit `yield` und `HTTPException` { #dependencies-with-yield-and-httpexception }
Sie haben gesehen, dass Ihre Abhängigkeiten `yield` verwenden können und `try`-Blöcke haben können, die Exceptions abfangen.
@@ -109,9 +109,27 @@ Aber es ist für Sie da, wenn Sie es brauchen. 🤓
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
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.
Eine Alternative zum Abfangen von Exceptions (und möglicherweise auch zum Auslösen einer weiteren `HTTPException`) besteht darin, einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} zu erstellen.
## Ausführung von Abhängigkeiten mit `yield`
## Abhängigkeiten mit `yield` und `except` { #dependencies-with-yield-and-except }
Wenn Sie eine Exception mit `except` in einer Abhängigkeit mit `yield` abfangen und sie nicht erneut auslösen (oder eine neue Exception auslösen), kann FastAPI nicht feststellen, dass es eine Exception gab, genau so wie es bei normalem Python der Fall wäre:
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
In diesem Fall sieht der Client eine *HTTP 500 Internal Server Error*-Response, wie es sein sollte, da wir keine `HTTPException` oder Ähnliches auslösen, aber der Server hat **keine Logs** oder einen anderen Hinweis darauf, was der Fehler war. 😱
### In Abhängigkeiten mit `yield` und `except` immer `raise` verwenden { #always-raise-in-dependencies-with-yield-and-except }
Wenn Sie eine Exception in einer Abhängigkeit mit `yield` abfangen, sollten Sie – sofern Sie nicht eine andere `HTTPException` oder Ähnliches auslösen – die ursprüngliche Exception erneut auslösen.
Sie können dieselbe Exception mit `raise` erneut auslösen:
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
Jetzt erhält der Client dieselbe *HTTP 500 Internal Server Error*-Response, aber der Server enthält unseren benutzerdefinierten `InternalError` in den Logs. 😎
## Ausführung von Abhängigkeiten mit `yield` { #execution-of-dependencies-with-yield }
Die Ausführungsreihenfolge ähnelt mehr oder weniger dem folgenden Diagramm. Die Zeit verläuft von oben nach unten. Und jede Spalte ist einer der interagierenden oder Code-ausführenden Teilnehmer.
@@ -135,22 +153,22 @@ participant tasks as Hintergrundtasks
opt Löst aus
operation -->> dep: Löst Exception aus (z. B. HTTPException)
opt Handhabt
dep -->> dep: Kann Exception abfangen, eine neue HTTPException auslösen, andere Exceptions auslösen
dep -->> handler: Leitet Exception automatisch weiter
dep -->> dep: Kann Exception abfangen, eine neue HTTPException auslösen, andere Exception auslösen
end
handler -->> client: HTTP-Error-Response
end
operation ->> client: Sendet Response an Client
Note over client,operation: Response wurde gesendet, kann nicht mehr geändert werden
Note over client,operation: Response wurde bereits gesendet, kann nicht mehr geändert werden
opt Tasks
operation -->> tasks: Sendet Hintergrundtasks
end
opt Löst andere Exception aus
tasks -->> tasks: Handhabt Exception im Hintergrundtask-Code
tasks -->> tasks: Handhabt Exceptions im Hintergrundtask-Code
end
```
/// info
/// info | Info
Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein.
@@ -160,13 +178,13 @@ Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesend
/// 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.
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#install-custom-exception-handlers){.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.
Wenn Sie eine Exception auslösen, wird sie an die Abhängigkeiten mit `yield` weitergegeben, einschließlich `HTTPException`. In den meisten Fällen sollten Sie dieselbe Exception oder eine neue aus der Abhängigkeit mit `yield` erneut auslösen, um sicherzustellen, dass sie korrekt gehandhabt wird.
///
## Abhängigkeiten mit `yield`, `HTTPException` und Hintergrundtasks
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | Achtung
@@ -176,7 +194,15 @@ Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI v
///
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.
### Abhängigkeiten mit `yield` und `except`, technische Details { #dependencies-with-yield-and-except-technical-details }
Vor FastAPI 0.110.0 war es so, dass wenn Sie eine Abhängigkeit mit `yield` verwendeten und dort eine Exception mit `except` abfingen und die Exception nicht erneut auslösten, diese Exception automatisch an Exceptionhandler oder den internen Serverfehler-Handler weitergereicht/ausgelöst wurde.
Dies wurde in Version 0.110.0 geändert, um unbehandelte Speichernutzung durch weitergereichte Exceptions ohne Handler (interne Serverfehler) zu beheben und um das Verhalten an regulären Python-Code anzugleichen.
### Hintergrundtasks und Abhängigkeiten mit `yield`, technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
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#install-custom-exception-handlers){.internal-link target=_blank} wären also bereits ausgeführt worden.
Dies wurde hauptsächlich so konzipiert, damit die gleichen Objekte, die durch Abhängigkeiten ge`yield`et werden, innerhalb von Hintergrundtasks verwendet werden können, da der Exit-Code ausgeführt wird, nachdem die Hintergrundtasks abgeschlossen sind.
@@ -194,9 +220,9 @@ Wenn Sie sich früher auf dieses Verhalten verlassen haben, sollten Sie jetzt di
Anstatt beispielsweise dieselbe Datenbanksitzung zu verwenden, würden Sie eine neue Datenbanksitzung innerhalb des Hintergrundtasks erstellen und die Objekte mithilfe dieser neuen Sitzung aus der Datenbank abrufen. Und anstatt das Objekt aus der Datenbank als Parameter an die Hintergrundtask-Funktion zu übergeben, würden Sie die ID dieses Objekts übergeben und das Objekt dann innerhalb der Hintergrundtask-Funktion erneut laden.
## Kontextmanager
## Kontextmanager { #context-managers }
### Was sind „Kontextmanager“
### Was sind „Kontextmanager“ { #what-are-context-managers }
„Kontextmanager“ (Englisch „Context Manager“) sind bestimmte Python-Objekte, die Sie in einer `with`-Anweisung verwenden können.
@@ -210,11 +236,11 @@ with open("./somefile.txt") as f:
Im Hintergrund erstellt das `open("./somefile.txt")` ein Objekt, das als „Kontextmanager“ bezeichnet wird.
Dieser stellt sicher dass, wenn der `with`-Block beendet ist, die Datei geschlossen wird, auch wenn Exceptions geworfen wurden.
Dieser stellt sicher, dass, wenn der `with`-Block beendet ist, die Datei geschlossen wird, auch wenn Exceptions geworfen wurden.
Wenn Sie eine Abhängigkeit mit `yield` erstellen, erstellt **FastAPI** dafür intern einen Kontextmanager und kombiniert ihn mit einigen anderen zugehörigen Tools.
### Kontextmanager in Abhängigkeiten mit `yield` verwenden
### Kontextmanager in Abhängigkeiten mit `yield` verwenden { #using-context-managers-in-dependencies-with-yield }
/// warning | Achtung
@@ -1,4 +1,4 @@
# Globale Abhängigkeiten
# Globale Abhängigkeiten { #global-dependencies }
Bei einigen Anwendungstypen möchten Sie möglicherweise Abhängigkeiten zur gesamten Anwendung hinzufügen.
@@ -8,8 +8,8 @@ In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[16] *}
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.
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 App.
## Abhängigkeiten für Gruppen von *Pfadoperationen*
## Abhängigkeiten für Gruppen von *Pfadoperationen* { #dependencies-for-groups-of-path-operations }
Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren.
Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Größere Anwendungen – mehrere Dateien](../../tutorial/bigger-applications.md){.internal-link target=_blank}), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren.
+24 -24
View File
@@ -1,10 +1,10 @@
# Abhängigkeiten
# Abhängigkeiten { #dependencies }
**FastAPI** hat ein sehr mächtiges, aber intuitives **<abbr title="Dependency Injection – Einbringen von Abhängigkeiten: Auch bekannt als Komponenten, Ressourcen, Provider, Services, Injectables">Dependency Injection</abbr>** System.
**FastAPI** hat ein sehr mächtiges, aber intuitives **<abbr title="auch bekannt als: Komponenten, Ressourcen, Provider, Services, Injectables">Dependency Injection</abbr>** System.
Es ist so konzipiert, sehr einfach zu verwenden zu sein und es jedem Entwickler sehr leicht zu machen, andere Komponenten mit **FastAPI** zu integrieren.
## Was ist „Dependency Injection“
## Was ist „Dependency Injection“ { #what-is-dependency-injection }
**„Dependency Injection“** bedeutet in der Programmierung, dass es für Ihren Code (in diesem Fall Ihre *Pfadoperation-Funktionen*) eine Möglichkeit gibt, Dinge zu deklarieren, die er verwenden möchte und die er zum Funktionieren benötigt: „Abhängigkeiten“ – „Dependencies“.
@@ -19,15 +19,15 @@ Das ist sehr nützlich, wenn Sie:
All dies, während Sie Codeverdoppelung minimieren.
## Erste Schritte
## Erste Schritte { #first-steps }
Sehen wir uns ein sehr einfaches Beispiel an. Es ist so einfach, dass es vorerst nicht sehr nützlich ist.
Aber so können wir uns besser auf die Funktionsweise des **Dependency Injection** Systems konzentrieren.
### Erstellen Sie eine Abhängigkeit (<abbr title="Das von dem abhängt, die zu verwendende Abhängigkeit">„Dependable“</abbr>)
### Eine Abhängigkeit erstellen, oder <abbr title="Das von dem abhängt, die zu verwendende Abhängigkeit">„Dependable“</abbr> { #create-a-dependency-or-dependable }
Konzentrieren wir uns zunächst auf die Abhängigkeit - die Dependency.
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*:
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *}
@@ -48,23 +48,23 @@ In diesem Fall erwartet diese Abhängigkeit:
* Einen optionalen Query-Parameter `skip`, der ein `int` ist und standardmäßig `0` ist.
* Einen optionalen Query-Parameter `limit`, der ein `int` ist und standardmäßig `100` ist.
Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält.
Und dann wird einfach ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> zurückgegeben, welches diese Werte enthält.
/// info
/// info | 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.
Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
///
### `Depends` importieren
### `Depends` importieren { #import-depends }
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *}
### Deklarieren der Abhängigkeit im <abbr title="Das Abhängige, der Verwender der Abhängigkeit">„Dependant“</abbr>
### Die Abhängigkeit im <abbr title="Das Abhängige, der Verwender der Abhängigkeit">„Dependant“</abbr> deklarieren { #declare-the-dependency-in-the-dependant }
So wie auch `Body`, `Query`, usw., verwenden Sie `Depends` mit den Parametern Ihrer *Pfadoperation-Funktion*:
@@ -86,7 +86,7 @@ Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen
///
Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum:
Immer wenn ein neuer <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> eintrifft, kümmert sich **FastAPI** darum:
* Ihre Abhängigkeitsfunktion („Dependable“) mit den richtigen Parametern aufzurufen.
* Sich das Ergebnis von dieser Funktion zu holen.
@@ -105,7 +105,7 @@ 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
/// check | Testen
Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich.
@@ -113,7 +113,7 @@ Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erled
///
## `Annotated`-Abhängigkeiten wiederverwenden
## `Annotated`-Abhängigkeiten wiederverwenden { #share-annotated-dependencies }
In den Beispielen oben sehen Sie, dass es ein kleines bisschen **Codeverdoppelung** gibt.
@@ -139,7 +139,7 @@ Die Abhängigkeiten funktionieren weiterhin wie erwartet, und das **Beste daran*
Das ist besonders nützlich, wenn Sie es in einer **großen Codebasis** verwenden, in der Sie in **vielen *Pfadoperationen*** immer wieder **dieselben Abhängigkeiten** verwenden.
## `async` oder nicht `async`
## `async` oder nicht `async` { #to-async-or-not-to-async }
Da Abhängigkeiten auch von **FastAPI** aufgerufen werden (so wie Ihre *Pfadoperation-Funktionen*), gelten beim Definieren Ihrer Funktionen die gleichen Regeln.
@@ -151,11 +151,11 @@ 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.
Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-a-hurry){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation.
///
## Integriert in OpenAPI
## Integriert in OpenAPI { #integrated-with-openapi }
Alle Requestdeklarationen, -validierungen und -anforderungen Ihrer Abhängigkeiten (und Unterabhängigkeiten) werden in dasselbe OpenAPI-Schema integriert.
@@ -163,9 +163,9 @@ Die interaktive Dokumentation enthält also auch alle Informationen aus diesen A
<img src="/img/tutorial/dependencies/image01.png">
## Einfache Verwendung
## Einfache Verwendung { #simple-usage }
Näher betrachtet, werden *Pfadoperation-Funktionen* deklariert, um verwendet zu werden, wann immer ein *Pfad* und eine *Operation* übereinstimmen, und dann kümmert sich **FastAPI** darum, die Funktion mit den richtigen Parametern aufzurufen, die Daten aus der Anfrage extrahierend.
Näher betrachtet, werden *Pfadoperation-Funktionen* deklariert, um verwendet zu werden, wann immer ein *Pfad* und eine *Operation* übereinstimmen, und dann kümmert sich **FastAPI** darum, die Funktion mit den richtigen Parametern aufzurufen, die Daten aus dem Request extrahierend.
Tatsächlich funktionieren alle (oder die meisten) Webframeworks auf die gleiche Weise.
@@ -181,7 +181,7 @@ Andere gebräuchliche Begriffe für dieselbe Idee der „Abhängigkeitsinjektion
* Injectables
* Komponenten
## **FastAPI**-Plugins
## **FastAPI**-Plugins { #fastapi-plug-ins }
Integrationen und „Plugins“ können mit dem **Dependency Injection** System erstellt werden. Aber tatsächlich besteht **keine Notwendigkeit, „Plugins“ zu erstellen**, da es durch die Verwendung von Abhängigkeiten möglich ist, eine unendliche Anzahl von Integrationen und Interaktionen zu deklarieren, die dann für Ihre *Pfadoperation-Funktionen* verfügbar sind.
@@ -189,7 +189,7 @@ Und Abhängigkeiten können auf sehr einfache und intuitive Weise erstellt werde
Beispiele hierfür finden Sie in den nächsten Kapiteln zu relationalen und NoSQL-Datenbanken, Sicherheit usw.
## **FastAPI**-Kompatibilität
## **FastAPI**-Kompatibilität { #fastapi-compatibility }
Die Einfachheit des Dependency Injection Systems macht **FastAPI** kompatibel mit:
@@ -199,10 +199,10 @@ Die Einfachheit des Dependency Injection Systems macht **FastAPI** kompatibel mi
* externen APIs
* Authentifizierungs- und Autorisierungssystemen
* API-Nutzungs-Überwachungssystemen
* Responsedaten-Injektionssystemen
* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Responsedaten</abbr>-Injektionssystemen
* usw.
## Einfach und leistungsstark
## Einfach und leistungsstark { #simple-and-powerful }
Obwohl das hierarchische Dependency Injection System sehr einfach zu definieren und zu verwenden ist, ist es dennoch sehr mächtig.
@@ -242,7 +242,7 @@ admin_user --> activate_user
paying_user --> pro_items
```
## Integriert mit **OpenAPI**
## Integriert mit **OpenAPI** { #integrated-with-openapi_1 }
Alle diese Abhängigkeiten, während sie ihre Anforderungen deklarieren, fügen auch Parameter, Validierungen, usw. zu Ihren *Pfadoperationen* hinzu.
@@ -1,4 +1,4 @@
# Unterabhängigkeiten
# Unterabhängigkeiten { #sub-dependencies }
Sie können Abhängigkeiten erstellen, die **Unterabhängigkeiten** haben.
@@ -6,17 +6,17 @@ Diese können so **tief** verschachtelt sein, wie nötig.
**FastAPI** kümmert sich darum, sie aufzulösen.
## Erste Abhängigkeit, „Dependable“
## Erste Abhängigkeit, „Dependable“ { #first-dependency-dependable }
Sie könnten eine erste Abhängigkeit („Dependable“) wie folgt erstellen:
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *}
Diese deklariert einen optionalen Abfrageparameter `q` vom Typ `str` und gibt ihn dann einfach zurück.
Diese deklariert einen optionalen Query-Parameter `q` vom Typ `str` und gibt ihn dann einfach zurück.
Das ist recht einfach (nicht sehr nützlich), hilft uns aber dabei, uns auf die Funktionsweise der Unterabhängigkeiten zu konzentrieren.
## Zweite Abhängigkeit, „Dependable“ und „Dependant“
## Zweite Abhängigkeit, „Dependable“ und „Dependant“ { #second-dependency-dependable-and-dependant }
Dann können Sie eine weitere Abhängigkeitsfunktion (ein „Dependable“) erstellen, die gleichzeitig eine eigene Abhängigkeit deklariert (also auch ein „Dependant“ ist):
@@ -29,17 +29,17 @@ Betrachten wir die deklarierten Parameter:
* Sie deklariert außerdem ein optionales `last_query`-Cookie, ein `str`.
* Wenn der Benutzer keine Query `q` übermittelt hat, verwenden wir die zuletzt übermittelte Query, die wir zuvor in einem Cookie gespeichert haben.
## Die Abhängigkeit verwenden
## Die Abhängigkeit verwenden { #use-the-dependency }
Diese Abhängigkeit verwenden wir nun wie folgt:
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *}
/// info
/// info | 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.
Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat an `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird.
///
@@ -54,13 +54,13 @@ read_query["/items/"]
query_extractor --> query_or_cookie_extractor --> read_query
```
## Dieselbe Abhängigkeit mehrmals verwenden
## Dieselbe Abhängigkeit mehrmals verwenden { #using-the-same-dependency-multiple-times }
Wenn eine Ihrer Abhängigkeiten mehrmals für dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhängigkeiten eine gemeinsame Unterabhängigkeit haben, wird **FastAPI** diese Unterabhängigkeit nur einmal pro Request aufrufen.
Wenn eine Ihrer Abhängigkeiten mehrmals für dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhängigkeiten eine gemeinsame Unterabhängigkeit haben, wird **FastAPI** diese Unterabhängigkeit nur einmal pro <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> aufrufen.
Und es speichert den zurückgegebenen Wert in einem <abbr title="Mechanismus, der bereits berechnete/generierte Werte zwischenspeichert, um sie später wiederzuverwenden, anstatt sie erneut zu berechnen.">„Cache“</abbr> und übergibt diesen gecachten Wert an alle „Dependanten“, die ihn in diesem spezifischen Request benötigen, anstatt die Abhängigkeit mehrmals für denselben Request aufzurufen.
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:
In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in demselben Request aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden:
//// tab | Python 3.8+
@@ -86,7 +86,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False
////
## Zusammenfassung
## Zusammenfassung { #recap }
Abgesehen von all den ausgefallenen Wörtern, die hier verwendet werden, ist das **Dependency Injection**-System recht simpel.
+3 -3
View File
@@ -1,12 +1,12 @@
# JSON-kompatibler Encoder
# JSON-kompatibler Encoder { #json-compatible-encoder }
Es gibt Fälle, da möchten Sie einen Datentyp (etwa ein Pydantic-Modell) in etwas konvertieren, das kompatibel mit JSON ist (etwa ein `dict`, eine `list`e, usw.).
Es gibt Fälle, da möchten Sie einen Datentyp (etwa ein Pydantic-Modell) in etwas konvertieren, das kompatibel mit JSON ist (etwa ein `dict`, eine `list`, usw.).
Zum Beispiel, wenn Sie es in einer Datenbank speichern möchten.
Dafür bietet **FastAPI** eine Funktion `jsonable_encoder()`.
## `jsonable_encoder` verwenden
## `jsonable_encoder` verwenden { #using-the-jsonable-encoder }
Stellen wir uns vor, Sie haben eine Datenbank `fake_db`, die nur JSON-kompatible Daten entgegennimmt.
+8 -8
View File
@@ -1,4 +1,4 @@
# Zusätzliche Datentypen
# Zusätzliche Datentypen { #extra-data-types }
Bisher haben Sie gängige Datentypen verwendet, wie zum Beispiel:
@@ -12,12 +12,12 @@ Sie können aber auch komplexere Datentypen verwenden.
Und Sie haben immer noch dieselbe Funktionalität wie bisher gesehen:
* Großartige Editor-Unterstützung.
* Datenkonvertierung bei eingehenden Requests.
* Datenkonvertierung für Response-Daten.
* Datenkonvertierung bei eingehenden <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr>.
* Datenkonvertierung für <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Daten.
* Datenvalidierung.
* Automatische Annotation und Dokumentation.
## Andere Datentypen
## Andere Datentypen { #other-data-types }
Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können:
@@ -36,11 +36,11 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können:
* `datetime.timedelta`:
* Ein Python-`datetime.timedelta`.
* Wird in Requests und Responses als `float` der Gesamtsekunden dargestellt.
* Pydantic ermöglicht auch die Darstellung als „ISO 8601 Zeitdifferenz-Kodierung“, <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#json_encoders" class="external-link" target="_blank">Weitere Informationen finden Sie in der Dokumentation</a>.
* Pydantic ermöglicht auch die Darstellung als „ISO 8601 Zeitdifferenz-Kodierung“, <a href="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers" class="external-link" target="_blank">siehe die Dokumentation für weitere Informationen</a>.
* `frozenset`:
* Wird in Requests und Responses wie ein `set` behandelt:
* Bei Requests wird eine Liste gelesen, Duplikate entfernt und in ein `set` umgewandelt.
* Bei Responses wird das `set` in eine `list`e umgewandelt.
* Bei Responses wird das `set` in eine `list` umgewandelt.
* Das generierte Schema zeigt an, dass die `set`-Werte eindeutig sind (unter Verwendung von JSON Schemas `uniqueItems`).
* `bytes`:
* Standard-Python-`bytes`.
@@ -49,9 +49,9 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können:
* `Decimal`:
* Standard-Python-`Decimal`.
* In Requests und Responses wird es wie ein `float` behandelt.
* Sie können alle gültigen Pydantic-Datentypen hier überprüfen: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic data types</a>.
* Sie können alle gültigen Pydantic-Datentypen hier überprüfen: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic-Datentypen</a>.
## Beispiel
## Beispiel { #example }
Hier ist ein Beispiel für eine *Pfadoperation* mit Parametern, die einige der oben genannten Typen verwenden.
+64 -61
View File
@@ -1,42 +1,42 @@
# Extramodelle
# Extramodelle { #extra-models }
Fahren wir beim letzten Beispiel fort. Es gibt normalerweise mehrere zusammengehörende Modelle.
Im Anschluss an das vorherige Beispiel ist es üblich, mehr als ein zusammenhängendes Modell zu haben.
Insbesondere Benutzermodelle, denn:
Dies gilt insbesondere für Benutzermodelle, denn:
* Das **hereinkommende Modell** sollte ein Passwort haben können.
* 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.
* Das **Eingabemodell** muss ein Passwort enthalten können.
* Das **Ausgabemodell** sollte kein Passwort haben.
* Das **Datenbankmodell** müsste wahrscheinlich ein gehashtes Passwort haben.
/// danger | Gefahr
Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können.
Speichern Sie niemals das Klartextpasswort eines Benutzers. Speichern Sie immer einen „sicheren Hash“, den Sie dann 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.
Wenn Sie nicht wissen, was das ist, werden Sie in den [Sicherheitskapiteln](security/simple-oauth2.md#password-hashing){.internal-link target=_blank} lernen, was ein „Passworthash“ ist.
///
## Mehrere Modelle
## Mehrere Modelle { #multiple-models }
Hier der generelle Weg, wie die Modelle mit ihren Passwort-Feldern aussehen könnten, und an welchen Orten sie verwendet werden würden.
Hier ist eine allgemeine Idee, wie die Modelle mit ihren Passwortfeldern aussehen könnten und an welchen Stellen sie verwendet werden:
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
/// info
/// info | Info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
In Pydantic v1 hieß die Methode `.dict()`, in Pydantic v2 wurde sie <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> (aber weiterhin 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.
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, aber Sie sollten `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
///
### Über `**user_in.dict()`
### Über `**user_in.dict()` { #about-user-in-dict }
#### Pydantic's `.dict()`
#### Die `.dict()`-Methode von Pydantic { #pydantics-dict }
`user_in` ist ein Pydantic-Modell der Klasse `UserIn`.
Pydantic-Modelle haben eine `.dict()`-Methode, die ein `dict` mit den Daten des Modells zurückgibt.
Pydantic-Modelle haben eine `.dict()`-Methode, die ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> mit den Daten des Modells zurückgibt.
Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so:
@@ -44,21 +44,21 @@ Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so:
user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
```
und wir rufen seine `.dict()`-Methode auf:
und dann aufrufen:
```Python
user_dict = user_in.dict()
```
dann haben wir jetzt in der Variable `user_dict` ein `dict` mit den gleichen Daten (es ist ein `dict` statt eines Pydantic-Modellobjekts).
haben wir jetzt ein `dict` mit den Daten in der Variablen `user_dict` (es ist ein `dict` statt eines Pydantic-Modellobjekts).
Wenn wir es ausgeben:
Und wenn wir aufrufen:
```Python
print(user_dict)
```
bekommen wir ein Python-`dict`:
würden wir ein Python-`dict` erhalten mit:
```Python
{
@@ -69,17 +69,17 @@ bekommen wir ein Python-`dict`:
}
```
#### Ein `dict` entpacken
#### Ein `dict` entpacken { #unpacking-a-dict }
Wenn wir ein `dict` wie `user_dict` nehmen, und es einer Funktion (oder Klassenmethode) mittels `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben.
Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben.
Wenn wir also das `user_dict` von oben nehmen und schreiben:
Setzen wir also das `user_dict` von oben ein:
```Python
UserInDB(**user_dict)
```
dann ist das ungefähr äquivalent zu:
so ist das äquivalent zu:
```Python
UserInDB(
@@ -90,7 +90,7 @@ UserInDB(
)
```
Oder, präziser, `user_dict` wird direkt verwendet, welche Werte es auch immer haben mag:
Oder genauer gesagt, dazu, `user_dict` direkt zu verwenden, mit welchen Inhalten es auch immer in der Zukunft haben mag:
```Python
UserInDB(
@@ -101,34 +101,34 @@ UserInDB(
)
```
#### Ein Pydantic-Modell aus den Inhalten eines anderen erstellen.
#### Ein Pydantic-Modell aus dem Inhalt eines anderen { #a-pydantic-model-from-the-contents-of-another }
Da wir in obigem Beispiel `user_dict` mittels `user_in.dict()` erzeugt haben, ist dieser Code:
Da wir im obigen Beispiel `user_dict` von `user_in.dict()` bekommen haben, wäre dieser Code:
```Python
user_dict = user_in.dict()
UserInDB(**user_dict)
```
äquivalent zu:
gleichwertig zu:
```Python
UserInDB(**user_in.dict())
```
... weil `user_in.dict()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es `UserInDB` übergeben, mit vorangestelltem `**`.
... weil `user_in.dict()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es an `UserInDB` mit vorangestelltem `**` übergeben.
Wir erhalten also ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells.
Auf diese Weise erhalten wir ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells.
#### Ein `dict` entpacken und zusätzliche Schlüsselwort-Argumente
#### Ein `dict` entpacken und zusätzliche Schlüsselwort-Argumente { #unpacking-a-dict-and-extra-keywords }
Und dann fügen wir ein noch weiteres Schlüsselwort-Argument hinzu, `hashed_password=hashed_password`:
Und dann fügen wir das zusätzliche Schlüsselwort-Argument `hashed_password=hashed_password` hinzu, wie in:
```Python
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
... was am Ende ergibt:
... was so ist wie:
```Python
UserInDB(
@@ -142,78 +142,81 @@ 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.
Die unterstützenden zusätzlichen Funktionen `fake_password_hasher` und `fake_save_user` dienen nur zur Demo eines möglichen Datenflusses, bieten jedoch natürlich keine echte Sicherheit.
///
## Verdopplung vermeiden
## Verdopplung vermeiden { #reduce-duplication }
Reduzierung von Code-Verdoppelung ist eine der Kern-Ideen von **FastAPI**.
Die Reduzierung von Code-Verdoppelung ist eine der Kernideen von **FastAPI**.
Weil Verdoppelung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Desynchronisation (Code wird nur an einer Stelle verändert, aber nicht an einer anderen), usw. erhöht.
Da die Verdopplung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Problemen mit der Desynchronisation des Codes (wenn Sie an einer Stelle, aber nicht an der anderen aktualisieren) usw. erhöht.
Unsere Modelle teilen alle eine Menge der Daten und verdoppeln Attribut-Namen und -Typen.
Und diese Modelle teilen alle eine Menge der Daten und verdoppeln Attributnamen und -typen.
Das können wir besser machen.
Wir könnten es besser machen.
Wir deklarieren ein `UserBase`-Modell, das als Basis für unsere anderen Modelle dient. Dann können wir Unterklassen erstellen, die seine Attribute (Typdeklarationen, Validierungen, usw.) erben.
Wir können ein `UserBase`-Modell deklarieren, das als Basis für unsere anderen Modelle dient. Und dann können wir Unterklassen dieses Modells erstellen, die seine Attribute (Typdeklarationen, Validierung usw.) erben.
Die ganze Datenkonvertierung, -validierung, -dokumentation, usw. wird immer noch wie gehabt funktionieren.
Die ganze Datenkonvertierung, -validierung, -dokumentation usw. wird immer noch wie gewohnt funktionieren.
Auf diese Weise beschreiben wir nur noch die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password`, und ohne Passwort):
Auf diese Weise können wir nur die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password` und ohne Passwort) deklarieren:
{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
## `Union`, oder `anyOf`
## `Union` oder `anyOf` { #union-or-anyof }
Sie können deklarieren, dass eine Response eine <abbr title="Union – Verbund, Einheit‚ Vereinigung: Eines von Mehreren">`Union`</abbr> mehrerer Typen ist, sprich, einer dieser Typen.
Sie können deklarieren, dass eine <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> eine <abbr title="Union – Verbund, Einheit, Vereinigung: Eines von Mehreren">`Union`</abbr> mehrerer Typen ist, das bedeutet, dass die Response einer von ihnen ist.
Das wird in OpenAPI mit `anyOf` angezeigt.
Dies wird in OpenAPI mit `anyOf` definiert.
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>:
Um das zu tun, verwenden Sie den Standard-Python-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`.
Wenn Sie eine <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a> definieren, listen Sie den spezifischeren Typ zuerst auf, gefolgt vom weniger spezifischen Typ. Im Beispiel unten steht `PlaneItem` vor `CarItem` in `Union[PlaneItem, CarItem]`.
///
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *}
### `Union` in Python 3.10
In diesem Beispiel übergeben wir dem Argument `response_model` den Wert `Union[PlaneItem, CarItem]`.
### `Union` in Python 3.10 { #union-in-python-3-10 }
Da wir es als **Wert einem Argument überreichen**, statt es als **Typannotation** zu verwenden, müssen wir `Union` verwenden, selbst in Python 3.10.
In diesem Beispiel übergeben wir `Union[PlaneItem, CarItem]` als Wert des Arguments `response_model`.
Wenn es eine Typannotation gewesen wäre, hätten wir auch den vertikalen Trennstrich verwenden können, wie in:
Da wir es als **Wert an ein Argument übergeben**, anstatt es in einer **Typannotation** zu verwenden, müssen wir `Union` verwenden, sogar in Python 3.10.
Wäre es eine Typannotation gewesen, hätten wir den vertikalen Strich verwenden können, wie in:
```Python
some_variable: PlaneItem | CarItem
```
Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, erhalten wir eine Fehlermeldung, da Python versucht, eine **ungültige Operation** zwischen `PlaneItem` und `CarItem` durchzuführen, statt es als Typannotation zu interpretieren.
Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, würden wir einen Fehler erhalten, weil Python versuchen würde, eine **ungültige Operation** zwischen `PlaneItem` und `CarItem` auszuführen, anstatt es als Typannotation zu interpretieren.
## Listen von Modellen
## Liste von Modellen { #list-of-models }
Genauso können Sie eine Response deklarieren, die eine Liste von Objekten ist.
Auf die gleiche Weise können Sie Responses von Listen von Objekten deklarieren.
Verwenden Sie dafür Pythons Standard `typing.List` (oder nur `list` in Python 3.9 und darüber):
Dafür verwenden Sie Pythons Standard-`typing.List` (oder nur `list` in Python 3.9 und höher):
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
## Response mit beliebigem `dict`
Sie könne auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, bei dem nur die Typen der Schlüssel und der Werte bekannt sind, ohne ein Pydantic-Modell zu verwenden.
## Response mit beliebigem `dict` { #response-with-arbitrary-dict }
Das ist nützlich, wenn Sie die gültigen Feld-/Attribut-Namen von vorneherein nicht wissen (was für ein Pydantic-Modell notwendig ist).
Sie können auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, indem Sie nur die Typen der Schlüssel und Werte ohne ein Pydantic-Modell deklarieren.
In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und darüber):
Dies ist nützlich, wenn Sie die gültigen Feld-/Attributnamen nicht im Voraus kennen (die für ein Pydantic-Modell benötigt werden würden).
In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und höher):
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
## Zusammenfassung
## Zusammenfassung { #recap }
Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf.
Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit verschiedene Zustände annehmen kann. So wie unsere Benutzer-„Einheit“, welche einen Zustand mit `password`, einen mit `password_hash` und einen ohne Passwort hatte.
Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit in der Lage sein muss, verschiedene „Zustände“ zu haben. Wie im Fall der Benutzer-„Einheit“ mit einem Zustand einschließlich `password`, `password_hash` und ohne Passwort.
+72 -84
View File
@@ -1,64 +1,80 @@
# Erste Schritte
# Erste Schritte { #first-steps }
Die einfachste FastAPI-Datei könnte wie folgt aussehen:
{* ../../docs_src/first_steps/tutorial001.py *}
Kopieren Sie dies in eine Datei `main.py`.
Kopieren Sie das in eine Datei `main.py`.
Starten Sie den Live-Server:
<div class="termy">
```console
$ uvicorn main:app --reload
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories
with <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
the following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
/// note | Hinweis
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:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Diese Zeile zeigt die URL, unter der Ihre Anwendung auf Ihrem lokalen Computer bereitgestellt wird.
Diese Zeile zeigt die URL, unter der Ihre App auf Ihrem lokalen Computer bereitgestellt wird.
### Testen Sie es
### Es testen { #check-it }
Öffnen Sie Ihren Browser unter <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000.</a>
Öffnen Sie Ihren Browser unter <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Sie werden folgende JSON-Response sehen:
Sie werden die JSON-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> sehen:
```JSON
{"message": "Hello World"}
```
### Interaktive API-Dokumentation
### Interaktive API-Dokumentation { #interactive-api-docs }
Gehen Sie als Nächstes auf <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs </a>.
Gehen Sie als Nächstes auf <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Sie werden die automatisch erzeugte, interaktive API-Dokumentation sehen (bereitgestellt durch <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternative API-Dokumentation
### Alternative API-Dokumentation { #alternative-api-docs }
Gehen Sie nun auf <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
@@ -66,31 +82,31 @@ Dort sehen Sie die alternative, automatische Dokumentation (bereitgestellt durch
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
### OpenAPI { #openapi }
**FastAPI** generiert ein „Schema“ mit all Ihren APIs unter Verwendung des **OpenAPI**-Standards zur Definition von APIs.
#### „Schema“
#### „Schema“ { #schema }
Ein „Schema“ ist eine Definition oder Beschreibung von etwas. Nicht der eigentliche Code, der es implementiert, sondern lediglich eine abstrakte Beschreibung.
#### API-„Schema“
#### API-„Schema“ { #api-schema }
In diesem Fall ist <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist.
In diesem Fall ist <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist.
Diese Schemadefinition enthält Ihre API-Pfade, die möglichen Parameter, welche diese entgegennehmen, usw.
#### Daten-„Schema“
#### Daten-„Schema“ { #data-schema }
Der Begriff „Schema“ kann sich auch auf die Form von Daten beziehen, wie z. B. einen JSON-Inhalt.
In diesem Fall sind die JSON-Attribute und deren Datentypen, usw. gemeint.
#### OpenAPI und JSON Schema
#### OpenAPI und JSON Schema { #openapi-and-json-schema }
OpenAPI definiert ein API-Schema für Ihre API. Dieses Schema enthält Definitionen (oder „Schemas“) der Daten, die von Ihrer API unter Verwendung von **JSON Schema**, dem Standard für JSON-Datenschemata, gesendet und empfangen werden.
#### Überprüfen Sie die `openapi.json`
#### Die `openapi.json` testen { #check-the-openapi-json }
Falls Sie wissen möchten, wie das rohe OpenAPI-Schema aussieht: FastAPI generiert automatisch ein JSON (Schema) mit den Beschreibungen Ihrer gesamten API.
@@ -119,7 +135,7 @@ Es wird ein JSON angezeigt, welches ungefähr so aussieht:
...
```
#### Wofür OpenAPI gedacht ist
#### Wofür OpenAPI gedacht ist { #what-is-openapi-for }
Das OpenAPI-Schema ist die Grundlage für die beiden enthaltenen interaktiven Dokumentationssysteme.
@@ -127,9 +143,9 @@ Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede d
Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen.
## Rückblick, Schritt für Schritt
## Zusammenfassung, Schritt für Schritt { #recap-step-by-step }
### Schritt 1: Importieren von `FastAPI`
### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi }
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
@@ -137,13 +153,13 @@ Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generier
/// note | Technische Details
`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt.
`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“
### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance }
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
@@ -151,37 +167,9 @@ In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI
Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein.
Die Variable `app` ist dieselbe, auf die sich der Befehl `uvicorn` bezieht:
### Schritt 3: Erstellen einer *Pfadoperation* { #step-3-create-a-path-operation }
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Wenn Sie Ihre Anwendung wie folgt erstellen:
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
Und in eine Datei `main.py` einfügen, dann würden Sie `uvicorn` wie folgt aufrufen:
<div class="termy">
```console
$ uvicorn main:my_awesome_api --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Schritt 3: Erstellen einer *Pfadoperation*
#### Pfad
#### Pfad { #path }
„Pfad“ bezieht sich hier auf den letzten Teil der URL, beginnend mit dem ersten `/`.
@@ -197,7 +185,7 @@ https://example.com/items/foo
/items/foo
```
/// info
/// info | Info
Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet.
@@ -205,7 +193,7 @@ 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“.
#### Operation
#### Operation { #operation }
„Operation“ bezieht sich hier auf eine der HTTP-„Methoden“.
@@ -240,16 +228,16 @@ In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichne
Wir werden sie auch „**Operationen**“ nennen.
#### Definieren eines *Pfadoperation-Dekorators*
#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von Anfragen zuständig ist, die an:
Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> zuständig ist, die an:
* den Pfad `/`
* unter der Verwendung der <abbr title="eine HTTP GET Methode"><code>get</code>-Operation</abbr> gehen
* den Pfad `/`
* unter der Verwendung der <abbr title="eine HTTP-GET-Methode"><code>get</code>-Operation</abbr> gehen
/// info | `@decorator` Information
/// info | `@decorator` Info
Diese `@something`-Syntax wird in Python „Dekorator“ genannt.
@@ -269,7 +257,7 @@ Sie können auch die anderen Operationen verwenden:
* `@app.put()`
* `@app.delete()`
Oder die exotischeren:
Und die exotischeren:
* `@app.options()`
* `@app.head()`
@@ -288,7 +276,7 @@ Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktion
///
### Schritt 4: Definieren der **Pfadoperation-Funktion**
### Schritt 4: Definieren der **Pfadoperation-Funktion** { #step-4-define-the-path-operation-function }
Das ist unsere „**Pfadoperation-Funktion**“:
@@ -300,7 +288,7 @@ Das ist unsere „**Pfadoperation-Funktion**“:
Dies ist eine Python-Funktion.
Sie wird von **FastAPI** immer dann aufgerufen, wenn sie eine Anfrage an die URL "`/`" mittels einer `GET`-Operation erhält.
Sie wird von **FastAPI** immer dann aufgerufen, wenn sie einen Request an die URL „`/`“ mittels einer `GET`-Operation erhält.
In diesem Fall handelt es sich um eine `async`-Funktion.
@@ -312,11 +300,11 @@ Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
/// note | Hinweis
Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-eile){.internal-link target=_blank}.
Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Schritt 5: den Inhalt zurückgeben
### Schritt 5: den Inhalt zurückgeben { #step-5-return-the-content }
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
@@ -324,12 +312,12 @@ Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurü
Sie können auch Pydantic-Modelle zurückgeben (dazu später mehr).
Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden.
Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs, usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden.
## Zusammenfassung
## Zusammenfassung { #recap }
* Importieren Sie `FastAPI`.
* Erstellen Sie eine `app` Instanz.
* Schreiben Sie einen **Pfadoperation-Dekorator** (wie z. B. `@app.get("/")`).
* Schreiben Sie eine **Pfadoperation-Funktion** (wie z. B. oben `def root(): ...`).
* Starten Sie den Entwicklungsserver (z. B. `uvicorn main:app --reload`).
* Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`.
* Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`.
* Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`.
+72 -72
View File
@@ -1,49 +1,49 @@
# Fehlerbehandlung
# Fehler behandeln { #handling-errors }
Es gibt viele Situationen, in denen Sie einem Client, der Ihre API benutzt, einen Fehler zurückgeben müssen.
Es gibt viele Situationen, in denen Sie einem Client, der Ihre API nutzt, einen Fehler mitteilen müssen.
Dieser Client könnte ein Browser mit einem Frontend, Code von jemand anderem, ein <abbr title="Internet of Things – Internet der Dinge: Geräte, die über das Internet Informationen austauschen">IoT</abbr>-Gerät, usw., sein.
Dieser Client könnte ein Browser mit einem Frontend sein, ein Code von jemand anderem, ein IoT-Gerät usw.
Sie müssten beispielsweise einem Client sagen:
Sie könnten dem Client mitteilen müssen, dass:
* Dass er nicht die notwendigen Berechtigungen hat, eine Aktion auszuführen.
* Dass er zu einer Ressource keinen Zugriff hat.
* Dass die Ressource, auf die er zugreifen möchte, nicht existiert.
* Der Client nicht genügend Berechtigungen für diese Operation hat.
* Der Client keinen Zugriff auf diese Ressource hat.
* Die Ressource, auf die der Client versucht hat, zuzugreifen, nicht existiert.
* usw.
In diesen Fällen geben Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (400 bis 499) zurück.
In diesen Fällen würden Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (von 400 bis 499) zurückgeben.
Das ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“er Statuscodes bedeuten, dass der Request in einem bestimmten Aspekt ein „Success“ („Erfolg“) war.
Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> in irgendeiner Weise erfolgreich war.
Die Statuscodes im 400er-Bereich bedeuten hingegen, dass es einen Fehler gab.
Die Statuscodes im Bereich 400 bedeuten hingegen, dass es einen Fehler seitens des Clients gab.
Erinnern Sie sich an all diese **404 Not Found** Fehler (und Witze)?
Erinnern Sie sich an all diese **„404 Not Found“** Fehler (und Witze)?
## `HTTPException` verwenden
## `HTTPException` verwenden { #use-httpexception }
Um HTTP-Responses mit Fehlern zum Client zurückzugeben, verwenden Sie `HTTPException`.
Um HTTP-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Responses</abbr> mit Fehlern an den Client zurückzugeben, verwenden Sie `HTTPException`.
### `HTTPException` importieren
### `HTTPException` importieren { #import-httpexception }
{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
### Eine `HTTPException` in Ihrem Code auslösen
### Eine `HTTPException` in Ihrem Code auslösen { #raise-an-httpexception-in-your-code }
`HTTPException` ist eine normale Python-<abbr title="Exception – Ausnahme, Fehler: Python-Objekt, das einen Fehler nebst Metadaten repräsentiert">Exception</abbr> mit einigen zusätzlichen Daten, die für APIs relevant sind.
`HTTPException` ist eine normale Python-Exception mit zusätzlichen Daten, die für APIs relevant sind.
Weil es eine Python-Exception ist, geben Sie sie nicht zurück, (`return`), sondern Sie lösen sie aus (`raise`).
Weil es eine Python-Exception ist, geben Sie sie nicht zurück (`return`), sondern lösen sie aus (`raise`).
Das bedeutet auch, wenn Sie in einer Hilfsfunktion sind, die Sie von ihrer *Pfadoperation-Funktion* aus aufrufen, und Sie lösen eine `HTTPException` von innerhalb dieser Hilfsfunktion aus, dann wird der Rest der *Pfadoperation-Funktion* nicht ausgeführt, sondern der Request wird sofort abgebrochen und der HTTP-Error der `HTTP-Exception` wird zum Client gesendet.
Das bedeutet auch, wenn Sie sich innerhalb einer Hilfsfunktion befinden, die Sie innerhalb Ihrer *Pfadoperation-Funktion* aufrufen, und Sie die `HTTPException` aus dieser Hilfsfunktion heraus auslösen, wird der restliche Code in der *Pfadoperation-Funktion* nicht ausgeführt. Der Request wird sofort abgebrochen und der HTTP-Error der `HTTPException` wird an den Client gesendet.
Der Vorteil, eine Exception auszulösen (`raise`), statt sie zurückzugeben (`return`) wird im Abschnitt über Abhängigkeiten und Sicherheit klarer werden.
Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wertes wird im Abschnitt über Abhängigkeiten und Sicherheit deutlicher werden.
Im folgenden Beispiel lösen wir, wenn der Client eine ID anfragt, die nicht existiert, eine Exception mit dem Statuscode `404` aus.
In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client einen Artikel mit einer nicht existierenden ID anfordert:
{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
### Die resultierende Response
### Die resultierende Response { #the-resulting-response }
Wenn der Client `http://example.com/items/foo` anfragt (ein `item_id` `"foo"`), erhält dieser Client einen HTTP-Statuscode 200 und folgende JSON-Response:
Wenn der Client `http://example.com/items/foo` anfordert (ein `item_id` `"foo"`), erhält dieser Client einen HTTP-Statuscode 200 und diese JSON-Response:
```JSON
{
@@ -51,7 +51,7 @@ Wenn der Client `http://example.com/items/foo` anfragt (ein `item_id` `"foo"`),
}
```
Aber wenn der Client `http://example.com/items/bar` anfragt (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Fehler), und eine JSON-Response wie folgt:
Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Error) und eine JSON-Response wie:
```JSON
{
@@ -61,41 +61,41 @@ 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`.
Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der in JSON konvertiert werden kann, nicht nur `str`.
Zum Beispiel ein `dict`, eine `list`, usw.
Sie könnten ein `dict`, eine `list`, usw. übergeben.
Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert.
Diese werden von **FastAPI** automatisch gehandhabt und in JSON konvertiert.
///
## Benutzerdefinierte Header hinzufügen
## Benutzerdefinierte Header hinzufügen { #add-custom-headers }
Es gibt Situationen, da ist es nützlich, dem HTTP-Error benutzerdefinierte Header hinzufügen zu können, etwa in einigen Sicherheitsszenarien.
Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel in einigen Sicherheitsszenarien.
Sie müssen das wahrscheinlich nicht direkt in ihrem Code verwenden.
Sie werden es wahrscheinlich nicht direkt in Ihrem Code verwenden müssen.
Aber falls es in einem fortgeschrittenen Szenario notwendig ist, können Sie benutzerdefinierte Header wie folgt hinzufügen:
Aber falls Sie es für ein fortgeschrittenes Szenario benötigen, können Sie benutzerdefinierte Header hinzufügen:
{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
## Benutzerdefinierte Exceptionhandler definieren
## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers }
Sie können benutzerdefinierte <abbr title="Exceptionhandler – Ausnahmebehandler: Funktion, die sich um die Bearbeitung einer Exception kümmert">Exceptionhandler</abbr> hinzufügen, mithilfe <a href="https://www.starlette.io/exceptions/" class="external-link" target="_blank">derselben Werkzeuge für Exceptions von Starlette</a>.
Sie können benutzerdefinierte <abbr title="Ausnahmebehandler: Funktion, die sich um die Bearbeitung einer Exception kümmert">Exceptionhandler</abbr> mit <a href="https://www.starlette.io/exceptions/" class="external-link" target="_blank">den gleichen Exception-Werkzeugen von Starlette</a> hinzufügen.
Nehmen wir an, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten.
Angenommen, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten.
Und Sie möchten diese Exception global mit FastAPI handhaben.
Sie könnten einen benutzerdefinierten Exceptionhandler mittels `@app.exception_handler()` hinzufügen:
Sie könnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufügen:
{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *}
Wenn Sie nun `/unicorns/yolo` anfragen, `raise`d die *Pfadoperation* eine `UnicornException`.
Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n.
Aber diese wird von `unicorn_exception_handler` gehandhabt.
Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-Inhalt:
Sie erhalten also einen sauberen Fehler mit einem HTTP-Statuscode von `418` und dem JSON-Inhalt:
```JSON
{"message": "Oops! yolo did something. There goes a rainbow..."}
@@ -103,33 +103,33 @@ Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-I
/// note | Technische Details
Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden.
Sie könnten 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`.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette. Dasselbe gilt für `Request`.
///
## Die Default-Exceptionhandler überschreiben
## Die Default-Exceptionhandler überschreiben { #override-the-default-exception-handlers }
**FastAPI** hat einige Default-Exceptionhandler.
Diese Handler kümmern sich darum, Default-JSON-Responses zurückzugeben, wenn Sie eine `HTTPException` `raise`n, und wenn der Request ungültige Daten enthält.
Diese Handler sind dafür verantwortlich, die Default-JSON-Responses zurückzugeben, wenn Sie eine `HTTPException` `raise`n und wenn der Request ungültige Daten enthält.
Sie können diese Exceptionhandler mit ihren eigenen überschreiben.
Sie können diese Exceptionhandler mit Ihren eigenen überschreiben.
### Requestvalidierung-Exceptions überschreiben
### Überschreiben von Request-Validierungs-Exceptions { #override-request-validation-exceptions }
Wenn ein Request ungültige Daten enthält, löst **FastAPI** intern einen `RequestValidationError` aus.
Und bietet auch einen Default-Exceptionhandler dafür.
Und es enthält auch einen Default-Exceptionhandler für diesen.
Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und verwenden Sie ihn in `@app.exception_handler(RequestValidationError)`, um Ihren Exceptionhandler zu dekorieren.
Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und verwenden Sie ihn mit `@app.exception_handler(RequestValidationError)`, um den Exceptionhandler zu dekorieren.
Der Exceptionhandler wird einen `Request` und die Exception entgegennehmen.
Der Exceptionhandler erhält einen `Request` und die Exception.
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
Wenn Sie nun `/items/foo` besuchen, erhalten Sie statt des Default-JSON-Errors:
Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit:
```JSON
{
@@ -146,7 +146,7 @@ Wenn Sie nun `/items/foo` besuchen, erhalten Sie statt des Default-JSON-Errors:
}
```
eine Textversion:
eine Textversion mit:
```
1 validation error
@@ -154,27 +154,27 @@ path -> item_id
value is not a valid integer (type=type_error.integer)
```
#### `RequestValidationError` vs. `ValidationError`
#### `RequestValidationError` vs. `ValidationError` { #requestvalidationerror-vs-validationerror }
/// warning | Achtung
Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind.
Dies sind technische Details, die Sie überspringen können, wenn sie für Sie jetzt 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>.
`RequestValidationError` ist eine Unterklasse von Pydantics <a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
**FastAPI** verwendet diesen, sodass Sie, wenn Sie ein Pydantic-Modell für `response_model` verwenden, und ihre Daten fehlerhaft sind, einen Fehler in ihrem Log sehen.
**FastAPI** verwendet diesen so, dass, wenn Sie ein Pydantic-Modell in `response_model` verwenden und Ihre Daten einen Fehler haben, Sie den Fehler in Ihrem Log sehen.
Aber der Client/Benutzer sieht ihn nicht. Stattdessen erhält der Client einen <abbr title="Interner Server-Fehler">„Internal Server Error“</abbr> mit einem HTTP-Statuscode `500`.
Aber der Client/Benutzer wird ihn nicht sehen. Stattdessen erhält der Client einen „Internal Server Error“ mit einem HTTP-Statuscode `500`.
Das ist, wie es sein sollte, denn wenn Sie einen Pydantic-`ValidationError` in Ihrer *Response* oder irgendwo sonst in ihrem Code haben (es sei denn, im *Request* des Clients), ist das tatsächlich ein Bug in ihrem Code.
Es sollte so sein, denn wenn Sie einen Pydantic `ValidationError` in Ihrer *Response* oder irgendwo anders in Ihrem Code haben (nicht im *Request* des Clients), ist es tatsächlich ein Fehler in Ihrem Code.
Und während Sie den Fehler beheben, sollten ihre Clients/Benutzer keinen Zugriff auf interne Informationen über den Fehler haben, da das eine Sicherheitslücke aufdecken könnte.
Und während Sie den Fehler beheben, sollten Ihre Clients/Benutzer keinen Zugriff auf interne Informationen über den Fehler haben, da das eine Sicherheitslücke aufdecken könnte.
### den `HTTPException`-Handler überschreiben
### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler }
Genauso können Sie den `HTTPException`-Handler überschreiben.
Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben.
Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen:
@@ -182,21 +182,21 @@ Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zu
/// note | Technische Details
Sie können auch `from starlette.responses import PlainTextResponse` verwenden.
Sie könnten 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.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette.
///
### Den `RequestValidationError`-Body verwenden
### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body }
Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten.
Sie könnten diesen verwenden, während Sie Ihre Anwendung entwickeln, um den Body zu loggen und zu debuggen, ihn zum Benutzer zurückzugeben, usw.
Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den Body zu loggen und zu debuggen, ihn an den Benutzer zurückzugeben usw.
{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
Jetzt versuchen Sie, einen ungültigen Artikel zu senden:
Versuchen Sie nun, einen ungültigen Artikel zu senden:
```JSON
{
@@ -205,7 +205,7 @@ Jetzt versuchen Sie, einen ungültigen Artikel zu senden:
}
```
Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und welche den empfangenen Body enthält.
Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind und die den empfangenen Body enthält:
```JSON hl_lines="12-15"
{
@@ -226,30 +226,30 @@ Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und w
}
```
#### FastAPIs `HTTPException` vs. Starlettes `HTTPException`
#### FastAPIs `HTTPException` vs. Starlettes `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception }
**FastAPI** hat seine eigene `HTTPException`.
Und **FastAPI**s `HTTPException`-Fehlerklasse erbt von Starlettes `HTTPException`-Fehlerklasse.
Und die `HTTPException`-Fehlerklasse von **FastAPI** erbt von der `HTTPException`-Fehlerklasse von Starlette.
Der einzige Unterschied besteht darin, dass **FastAPIs** `HTTPException` alles für das Feld `detail` akzeptiert, was nach JSON konvertiert werden kann, während Starlettes `HTTPException` nur Strings zulässt.
Der einzige Unterschied besteht darin, dass die `HTTPException` von **FastAPI** beliebige JSON-konvertierbare Daten für das `detail`-Feld akzeptiert, während die `HTTPException` von Starlette nur Strings dafür akzeptiert.
Sie können also weiterhin **FastAPI**s `HTTPException` wie üblich in Ihrem Code auslösen.
Sie können also weiterhin die `HTTPException` von **FastAPI** wie üblich in Ihrem Code auslösen.
Aber wenn Sie einen Exceptionhandler registrieren, registrieren Sie ihn für Starlettes `HTTPException`.
Aber wenn Sie einen Exceptionhandler registrieren, sollten Sie ihn für die `HTTPException` von Starlette registrieren.
Auf diese Weise wird Ihr Handler, wenn irgendein Teil von Starlettes internem Code, oder eine Starlette-Erweiterung, oder -Plugin eine Starlette-`HTTPException` auslöst, in der Lage sein, diese zu fangen und zu handhaben.
Auf diese Weise, wenn irgendein Teil des internen Codes von Starlette, oder eine Starlette-Erweiterung oder ein Plug-in, eine Starlette `HTTPException` auslöst, wird Ihr Handler in der Lage sein, diese abzufangen und zu handhaben.
Damit wir in diesem Beispiel beide `HTTPException`s im selben Code haben können, benennen wir Starlettes Exception um zu `StarletteHTTPException`:
Um in diesem Beispiel beide `HTTPException`s im selben Code zu haben, wird die Exception von Starlette zu `StarletteHTTPException` umbenannt:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
```
### **FastAPI**s Exceptionhandler wiederverwenden
### Die Exceptionhandler von **FastAPI** wiederverwenden { #reuse-fastapis-exception-handlers }
Wenn Sie die Exception zusammen mit denselben Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler von `fastapi.Exception_handlers` importieren und wiederverwenden:
Wenn Sie die Exception zusammen mit den gleichen Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler aus `fastapi.exception_handlers` importieren und wiederverwenden:
{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *}
In diesem Beispiel `print`en Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht, aber Sie sehen, worauf wir hinauswollen. Sie können mit der Exception etwas machen und dann einfach die Default-Exceptionhandler wiederverwenden.
In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie können die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden.
@@ -0,0 +1,72 @@
# Header-Parameter-Modelle { #header-parameter-models }
Wenn Sie eine Gruppe verwandter **Header-Parameter** haben, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren.
Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎
/// note | Hinweis
Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓
///
## Header-Parameter mit einem Pydantic-Modell { #header-parameters-with-a-pydantic-model }
Deklarieren Sie die erforderlichen **Header-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Header`:
{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *}
**FastAPI** wird die Daten für **jedes Feld** aus den **Headern** des <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> extrahieren und Ihnen das von Ihnen definierte Pydantic-Modell geben.
## Die Dokumentation testen { #check-the-docs }
Sie können die erforderlichen Header in der Dokumentationsoberfläche unter `/docs` sehen:
<div class="screenshot">
<img src="/img/tutorial/header-param-models/image01.png">
</div>
## Zusätzliche Header verbieten { #forbid-extra-headers }
In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die **Header einschränken**, die Sie erhalten möchten.
Sie können Pydantics Modellkonfiguration verwenden, um `extra` Felder zu verbieten (`forbid`):
{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *}
Wenn ein Client versucht, einige **zusätzliche Header** zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
Zum Beispiel, wenn der Client versucht, einen `tool`-Header mit einem Wert von `plumbus` zu senden, erhält er eine **Error-Response**, die ihm mitteilt, dass der Header-Parameter `tool` nicht erlaubt ist:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["header", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus",
}
]
}
```
## Automatische Umwandlung von Unterstrichen deaktivieren { #disable-convert-underscores }
Ähnlich wie bei regulären Header-Parametern werden bei der Verwendung von Unterstrichen in den Parameternamen diese **automatisch in Bindestriche umgewandelt**.
Wenn Sie beispielsweise einen Header-Parameter `save_data` im Code haben, wird der erwartete HTTP-Header `save-data` sein, und er wird auch so in der Dokumentation angezeigt.
Falls Sie aus irgendeinem Grund diese automatische Umwandlung deaktivieren müssen, können Sie dies auch für Pydantic-Modelle für Header-Parameter tun.
{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *}
/// warning | Achtung
Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass einige HTTP-Proxies und -Server die Verwendung von Headern mit Unterstrichen nicht zulassen.
///
## Zusammenfassung { #summary }
Sie können **Pydantic-Modelle** verwenden, um **Header** in **FastAPI** zu deklarieren. 😎
+28 -28
View File
@@ -1,50 +1,50 @@
# Header-Parameter
# Header-Parameter { #header-parameters }
So wie `Query`-, `Path`-, und `Cookie`-Parameter können Sie auch <abbr title='Header – Kopfzeilen, Header, Header-Felder: Schlüssel-Wert-Metadaten, die vom Client beim Request, und vom Server bei der Response gesendet werden'>Header</abbr>-Parameter definieren.
Sie können Header-Parameter genauso definieren, wie Sie `Query`-, `Path`- und `Cookie`-Parameter definieren.
## `Header` importieren
## `Header` importieren { #import-header }
Importieren Sie zuerst `Header`:
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
## `Header`-Parameter deklarieren
## `Header`-Parameter deklarieren { #declare-header-parameters }
Dann deklarieren Sie Ihre Header-Parameter, auf die gleiche Weise, wie Sie auch `Path`-, `Query`-, und `Cookie`-Parameter deklarieren.
Deklarieren Sie dann die Header-Parameter mit derselben Struktur wie bei `Path`, `Query` und `Cookie`.
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:
Sie können den Defaultwert sowie alle zusätzlichen Validierungs- oder Annotationsparameter definieren:
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
/// note | Technische Details
`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
`Header` ist eine „Schwester“-Klasse von `Path`, `Query` und `Cookie`. Sie erbt ebenfalls von der gemeinsamen `Param`-Klasse.
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.
Aber denken Sie daran, dass bei der Nutzung von `Query`, `Path`, `Header` und anderen Importen aus `fastapi`, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
///
/// info
/// info | Info
Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
Um Header zu deklarieren, müssen Sie `Header` verwenden, da die Parameter sonst als Query-Parameter interpretiert werden würden.
///
## Automatische Konvertierung
## Automatische Konvertierung { #automatic-conversion }
`Header` hat weitere Funktionalität, zusätzlich zu der, die `Path`, `Query` und `Cookie` bereitstellen.
`Header` bietet etwas zusätzliche Funktionalität im Vergleich zu `Path`, `Query` und `Cookie`.
Die meisten Standard-Header benutzen als Trennzeichen einen Bindestrich, auch bekannt als das „Minus-Symbol“ (`-`).
Die meisten Standard-Header sind durch ein „Bindestrich“-Zeichen getrennt, auch bekannt als „Minus-Symbol“ (`-`).
Aber eine Variable wie `user-agent` ist in Python nicht gültig.
Aber eine Variable wie `user-agent` ist in Python ungültig.
Darum wird `Header` standardmäßig in Parameternamen den Unterstrich (`_`) zu einem Bindestrich (`-`) konvertieren.
Daher wird `Header` standardmäßig die Zeichen des Parameter-Namens von Unterstrich (`_`) zu Bindestrich (`-`) konvertieren, um die Header zu extrahieren und zu dokumentieren.
HTTP-Header sind außerdem unabhängig von Groß-/Kleinschreibung, darum können Sie sie mittels der Standard-Python-Schreibweise deklarieren (auch bekannt als "snake_case").
Außerdem ist Groß-/Klein­schrei­bung in HTTP-Headern nicht relevant, daher können Sie sie im Standard-Python-Stil (auch bekannt als „snake_case“) deklarieren.
Sie können also `user_agent` schreiben, wie Sie es normalerweise in Python-Code machen würden, statt etwa die ersten Buchstaben groß zu schreiben, wie in `User_Agent`.
Sie können also `user_agent` verwenden, wie Sie es normalerweise im Python-Code tun würden, anstatt die Anfangsbuchstaben wie bei `User_Agent` großzuschreiben oder Ähnliches.
Wenn Sie aus irgendeinem Grund das automatische Konvertieren von Unterstrichen zu Bindestrichen abschalten möchten, setzen Sie den Parameter `convert_underscores` auf `False`.
Wenn Sie aus irgendeinem Grund die automatische Konvertierung von Unterstrichen zu Bindestrichen deaktivieren müssen, setzen Sie den Parameter `convert_underscores` von `Header` auf `False`:
{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
@@ -54,26 +54,26 @@ Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HT
///
## Doppelte Header
## Doppelte Header { #duplicate-headers }
Es ist möglich, doppelte Header zu empfangen. Also den gleichen Header mit unterschiedlichen Werten.
Es ist möglich, doppelte Header zu empfangen. Damit ist gemeint, denselben Header mit mehreren Werten.
Sie können solche Fälle deklarieren, indem Sie in der Typdeklaration eine Liste verwenden.
Sie können solche Fälle definieren, indem Sie in der Typdeklaration eine Liste verwenden.
Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`e.
Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`.
Um zum Beispiel einen Header `X-Token` zu deklarieren, der mehrmals vorkommen kann, schreiben Sie:
Um beispielsweise einen `X-Token`-Header zu deklarieren, der mehrmals vorkommen kann, können Sie schreiben:
{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
Wenn Sie mit einer *Pfadoperation* kommunizieren, die zwei HTTP-Header sendet, wie:
Wenn Sie mit dieser *Pfadoperation* kommunizieren und zwei HTTP-Header senden, wie:
```
X-Token: foo
X-Token: bar
```
Dann wäre die Response:
Dann wäre die <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>:
```JSON
{
@@ -84,8 +84,8 @@ Dann wäre die Response:
}
```
## Zusammenfassung
## Zusammenfassung { #recap }
Deklarieren Sie Header mittels `Header`, auf die gleiche Weise wie bei `Query`, `Path` und `Cookie`.
Deklarieren Sie Header mit `Header`, wobei Sie dasselbe gängige Muster wie bei `Query`, `Path` und `Cookie` verwenden.
Machen Sie sich keine Sorgen um Unterstriche in ihren Variablen, **FastAPI** wird sich darum kümmern, diese zu konvertieren.
Und machen Sie sich keine Sorgen um Unterstriche in Ihren Variablen, **FastAPI** wird sich darum kümmern, sie zu konvertieren.
+52 -40
View File
@@ -1,83 +1,95 @@
# Tutorial – Benutzerhandbuch
# Tutorial – Benutzerhandbuch { #tutorial-user-guide }
Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** und die meisten seiner Funktionen verwenden können.
Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** mit den meisten seiner Funktionen verwenden können.
Jeder Abschnitt baut schrittweise auf den vorhergehenden auf. Diese Abschnitte sind aber nach einzelnen Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre speziellen API-Anforderungen zu lösen.
Jeder Abschnitt baut schrittweise auf den vorhergehenden auf, ist jedoch in einzelne Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre spezifischen API-Anforderungen zu lösen.
Außerdem dienen diese als zukünftige Referenz.
Es ist auch so gestaltet, dass es als zukünftige Referenz dient, sodass Sie jederzeit zurückkommen und genau das sehen, was Sie benötigen.
Dadurch können Sie jederzeit zurückkommen und sehen genau das, was Sie benötigen.
## Den Code ausführen { #run-the-code }
## Den Code ausführen
Alle Codeblöcke können kopiert und direkt verwendet werden (es sind tatsächlich getestete Python-Dateien).
Alle Codeblöcke können kopiert und direkt verwendet werden (da es sich um getestete Python-Dateien handelt).
Um eines der Beispiele auszuführen, kopieren Sie den Code in eine Datei `main.py`, und starten Sie `uvicorn` mit:
Um eines der Beispiele auszuführen, kopieren Sie den Code in eine Datei `main.py` und starten Sie `fastapi dev` mit:
<div class="termy">
```console
$ uvicorn main:app --reload
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories
with <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
the following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
Es wird **ausdrücklich empfohlen**, dass Sie den Code schreiben oder kopieren, ihn bearbeiten und lokal ausführen.
Es wird **dringend empfohlen**, den Code zu schreiben oder zu kopieren, ihn zu bearbeiten und lokal auszuführen.
Die Verwendung in Ihrem eigenen Editor zeigt Ihnen die Vorteile von FastAPI am besten, wenn Sie sehen, wie wenig Code Sie schreiben müssen, all die Typprüfungen, die automatische Vervollständigung usw.
---
## FastAPI installieren
## FastAPI installieren { #install-fastapi }
Der erste Schritt besteht aus der Installation von FastAPI.
Der erste Schritt besteht darin, FastAPI zu installieren.
Für dieses Tutorial empfiehlt es sich, FastAPI mit allen optionalen Abhängigkeiten und Funktionen zu installieren:
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann **FastAPI installieren**:
<div class="termy">
```console
$ pip install "fastapi[all]"
$ pip install "fastapi[standard]"
---> 100%
```
</div>
... 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.
Wenn Sie mit `pip install "fastapi[standard]"` installieren, werden einige optionale Standard-Abhängigkeiten mit installiert, einschließlich `fastapi-cloud-cli`, welches Ihnen das Deployment in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> ermöglicht.
Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen:
Wenn Sie diese optionalen Abhängigkeiten nicht haben möchten, können Sie stattdessen `pip install fastapi` installieren.
```
pip install fastapi
```
Installieren Sie auch `uvicorn` als Server:
```
pip install "uvicorn[standard]"
```
Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten.
Wenn Sie die Standard-Abhängigkeiten, aber ohne das `fastapi-cloud-cli` installieren möchten, können Sie mit `pip install "fastapi[standard-no-fastapi-cloud-cli]"` installieren.
///
## Handbuch für fortgeschrittene Benutzer
## Handbuch für fortgeschrittene Benutzer { #advanced-user-guide }
Es gibt auch ein **Handbuch für fortgeschrittene Benutzer**, welches Sie später nach diesem **Tutorial – Benutzerhandbuch** lesen können.
Es gibt auch ein **Handbuch für fortgeschrittene Benutzer**, das Sie nach diesem **Tutorial – Benutzerhandbuch** lesen können.
Das **Handbuch für fortgeschrittene Benutzer** baut auf diesem Tutorial auf, verwendet dieselben Konzepte und bringt Ihnen einige zusätzliche Funktionen bei.
Das **Handbuch für fortgeschrittene Benutzer** baut hierauf auf, verwendet dieselben Konzepte und bringt Ihnen einige zusätzliche Funktionen bei.
Allerdings sollten Sie zuerst das **Tutorial – Benutzerhandbuch** lesen (was Sie hier gerade tun).
Sie sollten jedoch zuerst das **Tutorial – Benutzerhandbuch** lesen (was Sie gerade tun).
Die Dokumentation ist so konzipiert, dass Sie mit dem **Tutorial – Benutzerhandbuch** eine vollständige Anwendung erstellen können und diese dann je nach Bedarf mit einigen der zusätzlichen Ideen aus dem **Handbuch für fortgeschrittene Benutzer** vervollständigen können.
Es ist so konzipiert, dass Sie mit dem **Tutorial – Benutzerhandbuch** eine vollständige Anwendung erstellen können und diese dann je nach Bedarf mit einigen der zusätzlichen Ideen aus dem **Handbuch für fortgeschrittene Benutzer** erweitern können.
+31 -31
View File
@@ -1,10 +1,10 @@
# Metadaten und URLs der Dokumentationen
# Metadaten und Dokumentations-URLs { #metadata-and-docs-urls }
Sie können mehrere Metadaten-Einstellungen für Ihre **FastAPI**-Anwendung konfigurieren.
Sie können mehrere Metadaten-Konfigurationen in Ihrer **FastAPI**-Anwendung anpassen.
## Metadaten für die API
## Metadaten für die API { #metadata-for-api }
Sie können die folgenden Felder festlegen, welche in der OpenAPI-Spezifikation und den Benutzeroberflächen der automatischen API-Dokumentation verwendet werden:
Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und in den Benutzeroberflächen der automatischen API-Dokumentation verwendet werden:
| Parameter | Typ | Beschreibung |
|------------|------|-------------|
@@ -13,16 +13,16 @@ Sie können die folgenden Felder festlegen, welche in der OpenAPI-Spezifikation
| `description` | `str` | Eine kurze Beschreibung der API. Kann Markdown verwenden. |
| `version` | `string` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. |
| `terms_of_service` | `str` | Eine URL zu den Nutzungsbedingungen für die API. Falls angegeben, muss es sich um eine URL handeln. |
| `contact` | `dict` | Die Kontaktinformationen für die verfügbar gemachte API. Kann mehrere Felder enthalten. <details><summary><code>contact</code>-Felder</summary><table><thead><tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Der identifizierende Name der Kontaktperson/Organisation.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>Die URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Die E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Die Lizenzinformationen für die verfügbar gemachte API. Kann mehrere Felder enthalten. <details><summary><code>license_info</code>-Felder</summary><table><thead><tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ERFORDERLICH</strong> (wenn eine <code>license_info</code> festgelegt ist). Der für die API verwendete Lizenzname.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Ein <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a>-Lizenzausdruck für die API. Das Feld <code>identifier</code> und das Feld <code>url</code> schließen sich gegenseitig aus. <small>Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code >str</code></td><td>Eine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.</td></tr></tbody></table></details> |
| `contact` | `dict` | Die Kontaktinformationen für die freigegebene API. Kann mehrere Felder enthalten. <details><summary><code>contact</code>-Felder</summary><table><thead><tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Der identifizierende Name der Kontaktperson/Organisation.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>Die URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>Die E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.</td></tr></tbody></table></details> |
| `license_info` | `dict` | Die Lizenzinformationen für die freigegebene API. Kann mehrere Felder enthalten. <details><summary><code>license_info</code>-Felder</summary><table><thead><tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ERFORDERLICH</strong> (wenn eine <code>license_info</code> festgelegt ist). Der für die API verwendete Lizenzname.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Ein <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a>-Lizenzausdruck für die API. Das Feld <code>identifier</code> und das Feld <code>url</code> schließen sich gegenseitig aus. <small>Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>Eine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.</td></tr></tbody></table></details> |
Sie können diese wie folgt setzen:
{* ../../docs_src/metadata/tutorial001.py hl[3:16,19:32] *}
{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *}
/// tip | Tipp
Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert.
Sie können Markdown im Feld `description` verwenden, und es wird in der Ausgabe gerendert.
///
@@ -30,7 +30,7 @@ Mit dieser Konfiguration würde die automatische API-Dokumentation wie folgt aus
<img src="/img/tutorial/metadata/image01.png">
## Lizenz-ID
## Lizenzkennung { #license-identifier }
Seit OpenAPI 3.1.0 und FastAPI 0.99.0 können Sie die `license_info` auch mit einem `identifier` anstelle einer `url` festlegen.
@@ -38,29 +38,29 @@ Zum Beispiel:
{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
## Metadaten für Tags
## Metadaten für Tags { #metadata-for-tags }
Sie können mit dem Parameter `openapi_tags` auch zusätzliche Metadaten für die verschiedenen Tags hinzufügen, die zum Gruppieren Ihrer Pfadoperationen verwendet werden.
Sie können auch zusätzliche Metadaten für die verschiedenen Tags hinzufügen, die zum Gruppieren Ihrer Pfadoperationen verwendet werden, mit dem Parameter `openapi_tags`.
Es wird eine Liste benötigt, die für jedes Tag ein Dict enthält.
Er nimmt eine Liste entgegen, die für jeden Tag ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr> enthält.
Jedes Dict kann Folgendes enthalten:
Jedes Dictionary kann Folgendes enthalten:
* `name` (**erforderlich**): ein `str` mit demselben Tag-Namen, den Sie im Parameter `tags` in Ihren *Pfadoperationen* und `APIRouter`n verwenden.
* `description`: ein `str` mit einer kurzen Beschreibung für das Tag. Sie kann Markdown enthalten und wird in der Benutzeroberfläche der Dokumentation angezeigt.
* `externalDocs`: ein `dict`, das externe Dokumentation beschreibt mit:
* `description`: ein `str` mit einer kurzen Beschreibung für die externe Dokumentation.
* `url` (**erforderlich**): ein `str` mit der URL für die externe Dokumentation.
* `description`: ein `str` mit einer kurzen Beschreibung für die externe Dokumentation.
* `url` (**erforderlich**): ein `str` mit der URL für die externe Dokumentation.
### Metadaten für Tags erstellen
### Metadaten für Tags erstellen { #create-metadata-for-tags }
Versuchen wir das an einem Beispiel mit Tags für `users` und `items`.
Versuchen wir es mit einem Beispiel mit Tags für `users` und `items`.
Erstellen Sie Metadaten für Ihre Tags und übergeben Sie sie an den Parameter `openapi_tags`:
Erstellen Sie Metadaten für Ihre Tags und übergeben Sie diese an den Parameter `openapi_tags`:
{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
Beachten Sie, dass Sie Markdown in den Beschreibungen verwenden können. Beispielsweise wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden können. Zum Beispiel wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
/// tip | Tipp
@@ -68,31 +68,31 @@ Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
///
### Ihre Tags verwenden
### Ihre Tags verwenden { #use-your-tags }
Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen:
{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
/// info
/// info | Info
Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}.
///
### Die Dokumentation anschauen
### Die Dokumentation testen { #check-the-docs }
Wenn Sie nun die Dokumentation ansehen, werden dort alle zusätzlichen Metadaten angezeigt:
<img src="/img/tutorial/metadata/image02.png">
### Reihenfolge der Tags
### Reihenfolge der Tags { #order-of-tags }
Die Reihenfolge der Tag-Metadaten-Dicts definiert auch die Reihenfolge, in der diese in der Benutzeroberfläche der Dokumentation angezeigt werden.
Die Reihenfolge der Tag-Metadaten-Dictionarys definiert auch die Reihenfolge, in der diese in der Benutzeroberfläche der Dokumentation angezeigt werden.
Auch wenn beispielsweise `users` im Alphabet nach `items` kommt, wird es vor diesen angezeigt, da wir seine Metadaten als erstes Dict der Liste hinzugefügt haben.
Auch wenn beispielsweise `users` im Alphabet nach `items` kommt, wird es vor diesen angezeigt, da wir deren Metadaten als erstes Dictionary der Liste hinzugefügt haben.
## OpenAPI-URL
## OpenAPI-URL { #openapi-url }
Standardmäßig wird das OpenAPI-Schema unter `/openapi.json` bereitgestellt.
@@ -104,16 +104,16 @@ Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestel
Wenn Sie das OpenAPI-Schema vollständig deaktivieren möchten, können Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflächen deaktiviert werden, die es verwenden.
## URLs der Dokumentationen
## Dokumentations-URLs { #docs-urls }
Sie können die beiden enthaltenen Dokumentationsbenutzeroberflächen konfigurieren:
* **Swagger UI**: bereitgestellt unter `/docs`.
* Sie können deren URL mit dem Parameter `docs_url` festlegen.
* Sie können sie deaktivieren, indem Sie `docs_url=None` festlegen.
* Sie können deren URL mit dem Parameter `docs_url` festlegen.
* Sie können sie deaktivieren, indem Sie `docs_url=None` festlegen.
* **ReDoc**: bereitgestellt unter `/redoc`.
* Sie können deren URL mit dem Parameter `redoc_url` festlegen.
* Sie können sie deaktivieren, indem Sie `redoc_url=None` festlegen.
* Sie können deren URL mit dem Parameter `redoc_url` festlegen.
* Sie können sie deaktivieren, indem Sie `redoc_url=None` festlegen.
Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren:
+39 -10
View File
@@ -1,8 +1,8 @@
# Middleware
# Middleware { #middleware }
Sie können Middleware zu **FastAPI**-Anwendungen hinzufügen.
Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bevor er von einer bestimmten *Pfadoperation* verarbeitet wird. Und auch mit jeder **Response**, bevor sie zurückgegeben wird.
Eine „Middleware“ ist eine Funktion, die mit jedem **<abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr>** arbeitet, bevor er von einer bestimmten *Pfadoperation* verarbeitet wird. Und auch mit jeder **<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**, bevor sie zurückgegeben wird.
* Sie nimmt jeden **Request** entgegen, der an Ihre Anwendung gesendet wird.
* Sie kann dann etwas mit diesem **Request** tun oder beliebigen Code ausführen.
@@ -15,11 +15,11 @@ Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bev
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.
Wenn es Hintergrundtasks gab (dies wird später im [Hintergrundtasks](background-tasks.md){.internal-link target=_blank}-Abschnitt behandelt), werden sie *nach* allen Middlewares ausgeführt.
///
## Erstellung einer Middleware
## Eine Middleware erstellen { #create-a-middleware }
Um eine Middleware zu erstellen, verwenden Sie den Dekorator `@app.middleware("http")` über einer Funktion.
@@ -35,9 +35,9 @@ Die Middleware-Funktion erhält:
/// 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>.
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">unter Verwendung des `X-`-Präfixes</a>.
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.
Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfiguration ([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">Starlettes CORS-Dokumentation</a> dokumentiert ist.
///
@@ -49,7 +49,7 @@ Sie könnten auch `from starlette.requests import Request` verwenden.
///
### Vor und nach der `response`
### Vor und nach der `response` { #before-and-after-the-response }
Sie können Code hinzufügen, der mit dem `request` ausgeführt wird, bevor dieser von einer beliebigen *Pfadoperation* empfangen wird.
@@ -59,8 +59,37 @@ Sie könnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hi
{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
## Andere Middlewares
/// tip | Tipp
Sie können später mehr über andere Middlewares in [Handbuch für fortgeschrittene Benutzer: Fortgeschrittene Middleware](../advanced/middleware.md){.internal-link target=_blank} lesen.
Hier verwenden wir <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> anstelle von `time.time()`, da es für diese Anwendungsfälle präziser sein kann. 🤓
In der nächsten Sektion erfahren Sie, wie Sie <abbr title="Cross-Origin Resource Sharing">CORS</abbr> mit einer Middleware behandeln können.
///
## Ausführungsreihenfolge bei mehreren Middlewares { #multiple-middleware-execution-order }
Wenn Sie mehrere Middlewares hinzufügen, entweder mit dem `@app.middleware()` Dekorator oder der Methode `app.add_middleware()`, umschließt jede neue Middleware die Anwendung und bildet einen Stapel. Die zuletzt hinzugefügte Middleware ist die *äußerste*, und die erste ist die *innerste*.
Auf dem Requestpfad läuft die *äußerste* Middleware zuerst.
Auf dem Responsepfad läuft sie zuletzt.
Zum Beispiel:
```Python
app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)
```
Dies führt zu folgender Ausführungsreihenfolge:
* **Request**: MiddlewareB → MiddlewareA → Route
* **Response**: Route → MiddlewareA → MiddlewareB
Dieses Stapelverhalten stellt sicher, dass Middlewares in einer vorhersehbaren und kontrollierbaren Reihenfolge ausgeführt werden.
## Andere Middlewares { #other-middlewares }
Sie können später mehr über andere Middlewares im [Handbuch für fortgeschrittene Benutzer: Fortgeschrittene Middleware](../advanced/middleware.md){.internal-link target=_blank} lesen.
In der nächsten Sektion erfahren Sie, wie Sie <abbr title="Cross-Origin Resource Sharing – Ressourcenfreigabe zwischen Ursprüngen">CORS</abbr> mit einer Middleware behandeln können.
@@ -1,6 +1,6 @@
# Pfadoperation-Konfiguration
# Pfadoperation-Konfiguration { #path-operation-configuration }
Es gibt mehrere Konfigurations-Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können.
Es gibt mehrere Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können, um ihn zu konfigurieren.
/// warning | Achtung
@@ -8,13 +8,13 @@ Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeb
///
## Response-Statuscode
## Response-Statuscode { #response-status-code }
Sie können den (HTTP-)`status_code` definieren, den die Response Ihrer *Pfadoperation* verwenden soll.
Sie können den (HTTP-)`status_code` definieren, der in der <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> Ihrer *Pfadoperation* verwendet werden soll.
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:
Aber falls Sie sich nicht mehr erinnern, wofür jeder Nummerncode steht, können Sie die Abkürzungs-Konstanten in `status` verwenden:
{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *}
@@ -28,9 +28,9 @@ Sie können auch `from starlette import status` verwenden.
///
## Tags
## Tags { #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`):
Sie können Ihrer *Pfadoperation* Tags hinzufügen, indem Sie dem Parameter `tags` eine `list`e von `str`s übergeben (in der Regel nur ein `str`):
{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *}
@@ -38,47 +38,47 @@ Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumenta
<img src="/img/tutorial/path-operation-configuration/image01.png">
### Tags mittels Enumeration
### Tags mittels Enumeration { #tags-with-enums }
Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** nehmen.
Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden.
In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern.
**FastAPI** unterstützt diese genauso wie einfache Strings:
**FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings:
{* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *}
## Zusammenfassung und Beschreibung
## Zusammenfassung und Beschreibung { #summary-and-description }
Sie können eine Zusammenfassung (`summary`) und eine Beschreibung (`description`) hinzufügen:
Sie können eine <abbr title="Zusammenfassung">`summary`</abbr> und eine <abbr title="Beschreibung">`description`</abbr> hinzufügen:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## Beschreibung mittels Docstring
## Beschreibung mittels Docstring { #description-from-docstring }
Da Beschreibungen oft mehrere Zeilen lang sind, können Sie die Beschreibung der *Pfadoperation* im <abbr title="Ein mehrzeiliger String (keiner Variable zugewiesen) als erster Ausdruck in einer Funktion, wird für die Dokumentation derselben verwendet">Docstring</abbr> der Funktion deklarieren, und **FastAPI** wird sie daraus auslesen.
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).
Sie können <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> im Docstring schreiben, es wird korrekt interpretiert und angezeigt (unter Berücksichtigung der Einrückung des Docstring).
{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *}
In der interaktiven Dokumentation sieht das dann so aus:
Es wird in der interaktiven Dokumentation verwendet:
<img src="/img/tutorial/path-operation-configuration/image02.png">
## Beschreibung der Response
## Beschreibung der Response { #response-description }
Die Response können Sie mit dem Parameter `response_description` beschreiben:
Sie können die Response mit dem Parameter `response_description` beschreiben:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info
/// info | Info
beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
Beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
///
/// check
/// check | Testen
OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt.
@@ -88,13 +88,13 @@ Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolg
<img src="/img/tutorial/path-operation-configuration/image03.png">
## Eine *Pfadoperation* deprecaten
## Eine *Pfadoperation* deprecaten { #deprecate-a-path-operation }
Wenn Sie eine *Pfadoperation* als <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu:
Wenn Sie eine *Pfadoperation* als <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu:
{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *}
Sie wird in der interaktiven Dokumentation gut sichtbar als deprecated markiert werden:
Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden:
<img src="/img/tutorial/path-operation-configuration/image04.png">
@@ -102,6 +102,6 @@ Vergleichen Sie, wie deprecatete und nicht-deprecatete *Pfadoperationen* aussehe
<img src="/img/tutorial/path-operation-configuration/image05.png">
## Zusammenfassung
## Zusammenfassung { #recap }
Sie können auf einfache Weise Metadaten für Ihre *Pfadoperationen* definieren, indem Sie den *Pfadoperation-Dekoratoren* Parameter hinzufügen.
@@ -1,60 +1,56 @@
# Pfad-Parameter und Validierung von Zahlen
# Pfad-Parameter und Validierung von Zahlen { #path-parameters-and-numeric-validations }
So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metadaten hinzufügen können, können Sie das mittels `Path` auch für Pfad-Parameter tun.
So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metadaten deklarieren können, können Sie mit `Path` die gleichen Validierungen und Metadaten für Pfad-Parameter deklarieren.
## `Path` importieren
## `Path` importieren { #import-path }
Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`.
Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`:
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
/// info
/// info | Info
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
FastAPI hat in Version 0.95.0 Unterstützung für `Annotated` hinzugefügt und es zur Verwendung empfohlen.
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
Wenn Sie eine ältere Version haben, würden Fehler angezeigt werden, 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.
Stellen Sie sicher, dass Sie [FastAPI aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}, auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden.
///
## Metadaten deklarieren
## Metadaten deklarieren { #declare-metadata }
Sie können die gleichen Parameter deklarieren wie für `Query`.
Sie können dieselben Parameter wie für `Query` deklarieren.
Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, schreiben Sie:
Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, können Sie schreiben:
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
/// 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.
Ein Pfad-Parameter ist immer erforderlich, da er Teil des Pfads sein muss. Selbst wenn Sie ihn mit `None` deklarieren oder einen Defaultwert setzen, würde das nichts ändern, er wäre dennoch immer erforderlich.
///
## Sortieren Sie die Parameter, wie Sie möchten
## Die Parameter sortieren, wie Sie möchten { #order-the-parameters-as-you-need }
/// tip | Tipp
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden.
///
Nehmen wir an, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren.
Angenommen, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren.
Und Sie müssen sonst nichts anderes für den Parameter deklarieren, Sie brauchen also nicht wirklich `Query`.
Und Sie müssen sonst nichts anderes für diesen Parameter deklarieren, Sie brauchen also `Query` nicht wirklich.
Aber Sie brauchen `Path` für den `item_id`-Pfad-Parameter. Und Sie möchten aus irgendeinem Grund nicht `Annotated` verwenden.
Aber Sie müssen dennoch `Path` für den `item_id`-Pfad-Parameter verwenden. Und aus irgendeinem Grund möchten Sie `Annotated` nicht verwenden.
Python wird sich beschweren, wenn Sie einen Parameter mit Defaultwert vor einen Parameter ohne Defaultwert setzen.
Python wird sich beschweren, wenn Sie einen Wert mit einem „Default“ vor einem Wert ohne „Default“ setzen.
Aber Sie können die Reihenfolge der Parameter ändern, den Query-Parameter ohne Defaultwert zuerst.
Aber Sie können die Reihenfolge ändern und den Wert ohne Default (den Query-Parameter `q`) zuerst setzen.
Für **FastAPI** ist es nicht wichtig. Es erkennt die Parameter anhand ihres Namens, ihrer Typen, und ihrer Defaultwerte (`Query`, `Path`, usw.). Es kümmert sich nicht um die Reihenfolge.
Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Namen, Typen und Default-Deklarationen (`Query`, `Path`, usw.), es kümmert sich nicht um die Reihenfolge.
Sie können Ihre Funktion also so deklarieren:
@@ -66,104 +62,103 @@ Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="7"
{!> ../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
////
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.
Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden.
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
## Sortieren Sie die Parameter wie Sie möchten: Tricks
## Die Parameter sortieren, wie Sie möchten: Tricks { #order-the-parameters-as-you-need-tricks }
/// tip | Tipp
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden.
///
Hier ein **kleiner Trick**, der nützlich sein kann, aber Sie werden ihn nicht oft brauchen.
Hier ist ein **kleiner Trick**, der nützlich sein kann, obwohl Sie ihn nicht oft benötigen werden.
Wenn Sie eines der folgenden Dinge tun möchten:
Wenn Sie:
* den `q`-Parameter ohne `Query` oder irgendeinem Defaultwert deklarieren
* den Pfad-Parameter `item_id` mittels `Path` deklarieren
* die Parameter in einer unterschiedlichen Reihenfolge haben
* `Annotated` nicht verwenden
* den `q`-Query-Parameter sowohl ohne `Query` als auch ohne Defaultwert deklarieren
* den Pfad-Parameter `item_id` mit `Path` deklarieren
* sie in einer anderen Reihenfolge haben
* nicht `Annotated` verwenden
... dann hat Python eine kleine Spezial-Syntax für Sie.
... möchten, dann hat Python eine kleine Spezial-Syntax dafür.
Übergeben Sie der Funktion `*` als ersten Parameter.
Übergeben Sie `*`, als den ersten Parameter der Funktion.
Python macht nichts mit diesem `*`, aber es wird wissen, dass alle folgenden Parameter als <abbr title="Keyword-Argument – Schlüsselwort-Argument: Das Argument wird anhand seines Namens erkannt, nicht anhand seiner Reihenfolge in der Argumentliste">Keyword-Argumente</abbr> (Schlüssel-Wert-Paare), auch bekannt als <abbr title="Von: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>, verwendet werden. Selbst wenn diese keinen Defaultwert haben.
Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlüsselwortargumente (Schlüssel-Wert-Paare) verwendet werden sollen, auch bekannt als <abbr title="Von: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Selbst wenn diese keinen Defaultwert haben.
{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
### Besser mit `Annotated`
### Besser mit `Annotated` { #better-with-annotated }
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.
Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, da Sie keine Funktionsparameter-Defaultwerte verwenden, dieses Problem nicht haben werden und wahrscheinlich nicht `*` verwenden müssen.
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
## Validierung von Zahlen: Größer oder gleich
## Validierung von Zahlen: Größer oder gleich { #number-validations-greater-than-or-equal }
Mit `Query` und `Path` (und anderen, die Sie später kennenlernen), können Sie Zahlenbeschränkungen deklarieren.
Mit `Query` und `Path` (und anderen, die Sie später sehen werden) können Sie Zahlenbeschränkungen deklarieren.
Hier, mit `ge=1`, muss `item_id` eine ganze Zahl sein, die „`g`reater than or `e`qual to“ (größer oder gleich) `1` ist.
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).
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
## Validierung von Zahlen: Größer und kleiner oder gleich
## Validierung von Zahlen: Größer und kleiner oder gleich { #number-validations-greater-than-and-less-than-or-equal }
Das Gleiche trifft zu auf:
Das Gleiche gilt für:
* `gt`: `g`reater `t`han – größer als
* `le`: `l`ess than or `e`qual – kleiner oder gleich
* `gt`: `g`reater `t`han (größer als)
* `le`: `l`ess than or `e`qual (kleiner oder gleich)
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
## Validierung von Zahlen: Floats, größer und kleiner
## Validierung von Zahlen: Floats, größer und kleiner { #number-validations-floats-greater-than-and-less-than }
Zahlenvalidierung funktioniert auch für <abbr title="Kommazahl">`float`</abbr>-Werte.
Zahlenvalidierung funktioniert auch für <abbr title="Fließkommazahlen">`float`</abbr>-Werte.
Hier wird es wichtig, in der Lage zu sein, <abbr title="greater than – größer als"><code>gt</code></abbr> zu deklarieren, und nicht nur <abbr title="greater than or equal – größer oder gleich"><code>ge</code></abbr>, da Sie hiermit bestimmen können, dass ein Wert, zum Beispiel, größer als `0` sein muss, obwohl er kleiner als `1` ist.
Hier wird es wichtig, in der Lage zu sein, <abbr title="greater than – größer als"><code>gt</code></abbr> und nicht nur <abbr title="greater than or equal – größer oder gleich"><code>ge</code></abbr> zu deklarieren. Da Sie mit dieser Option erzwingen können, dass ein Wert größer als `0` sein muss, selbst wenn er kleiner als `1` ist.
`0.5` wäre also ein gültiger Wert, aber nicht `0.0` oder `0`.
Also wäre `0.5` ein gültiger Wert. Aber `0.0` oder `0` nicht.
Das gleiche gilt für <abbr title="less than – kleiner als"><code>lt</code></abbr>.
Und das Gleiche gilt für <abbr title="less than – kleiner als"><code>lt</code></abbr>.
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
## Zusammenfassung
## Zusammenfassung { #recap }
Mit `Query` und `Path` (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen deklarieren, so wie in [Query-Parameter und Stringvalidierungen](query-params-str-validations.md){.internal-link target=_blank} beschrieben.
Mit `Query`, `Path` (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen auf die gleichen Weisen deklarieren wie in [Query-Parameter und Stringvalidierungen](query-params-str-validations.md){.internal-link target=_blank} beschrieben.
Und Sie können auch Validierungen für Zahlen deklarieren:
Und Sie können auch Zahlenvalidierungen deklarieren:
* `gt`: `g`reater `t`han – größer als
* `ge`: `g`reater than or `e`qual – größer oder gleich
* `lt`: `l`ess `t`han – kleiner als
* `le`: `l`ess than or `e`qual – kleiner oder gleich
* `gt`: `g`reater `t`han (größer als)
* `ge`: `g`reater than or `e`qual (größer oder gleich)
* `lt`: `l`ess `t`han (kleiner als)
* `le`: `l`ess than or `e`qual (kleiner oder gleich)
/// info
/// info | Info
`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse.
`Query`, `Path`, und andere Klassen, die Sie später sehen werden, sind Unterklassen einer gemeinsamen `Param`-Klasse.
Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
Alle von ihnen teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
///
/// note | Technische Details
`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen.
Wenn Sie `Query`, `Path` und andere von `fastapi` importieren, sind sie tatsächlich Funktionen.
Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.
Die, wenn sie aufgerufen werden, Instanzen von 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.
Sie importieren also `Query`, was eine Funktion ist. Und wenn Sie sie aufrufen, gibt sie eine Instanz einer 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.
Auf diese Weise können Sie Ihren normalen Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.
///
+38 -38
View File
@@ -1,18 +1,18 @@
# Pfad-Parameter
# Pfad-Parameter { #path-parameters }
Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-<abbr title="Format-String – Formatierter String: Der String enthält Variablen, die mit geschweiften Klammern umschlossen sind. Solche Stellen werden durch den Wert der Variable ersetzt">Format-Strings</abbr> verwendet wird:
Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-<abbr title="Formatstring – Formatierter String: Der String enthält Ausdrücke, die mit geschweiften Klammern umschlossen sind. Solche Stellen werden durch den Wert des Ausdrucks ersetzt">Formatstrings</abbr> verwendet wird:
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` übergeben.
Wenn Sie dieses Beispiel ausführen und auf <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> gehen, sehen Sie als Response:
Wenn Sie dieses Beispiel ausführen und auf <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> gehen, sehen Sie als <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>:
```JSON
{"item_id":"foo"}
```
## Pfad-Parameter mit Typen
## Pfad-Parameter mit Typen { #path-parameters-with-types }
Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion deklarieren, mit Standard-Python-Typannotationen:
@@ -20,13 +20,13 @@ 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
/// check | Testen
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>
## Daten-<abbr title="Auch bekannt als: Serialisierung, Parsen, Marshalling">Konversion</abbr> { #data-conversion }
Wenn Sie dieses Beispiel ausführen und Ihren Browser unter <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a> öffnen, sehen Sie als Response:
@@ -34,15 +34,15 @@ Wenn Sie dieses Beispiel ausführen und Ihren Browser unter <a href="http://127.
{"item_id":3}
```
/// check
/// check | Testen
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>.
Sprich, mit dieser Typdeklaration wird **FastAPI** den <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> automatisch <abbr title="Den String, der von einem HTTP-Request kommt, in Python-Objekte konvertieren">„parsen“</abbr>.
///
## Datenvalidierung
## Datenvalidierung { #data-validation }
Wenn Sie aber im Browser <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> besuchen, erhalten Sie eine hübsche HTTP-Fehlermeldung:
@@ -66,23 +66,23 @@ 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
/// check | Testen
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung.
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.
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit Ihrer API interagiert.
///
## Dokumentation
## Dokumentation { #documentation }
Wenn Sie die Seite <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> in Ihrem Browser öffnen, sehen Sie eine automatische, interaktive API-Dokumentation:
<img src="/img/tutorial/path-params/image01.png">
/// check
/// check | Testen
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
@@ -90,7 +90,7 @@ Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
///
## Nützliche Standards. Alternative Dokumentation
## Nützliche Standards, alternative Dokumentation { #standards-based-benefits-alternative-documentation }
Und weil das generierte Schema vom <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a>-Standard kommt, gibt es viele kompatible Tools.
@@ -100,15 +100,15 @@ Zum Beispiel bietet **FastAPI** selbst eine alternative API-Dokumentation (verwe
Und viele weitere kompatible Tools. Inklusive Codegenerierung für viele Sprachen.
## Pydantic
## Pydantic { #pydantic }
Die ganze Datenvalidierung wird hinter den Kulissen von <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind.
Die ganze Datenvalidierung wird hinter den Kulissen von <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind.
Sie können für Typ Deklarationen auch `str`, `float`, `bool` und viele andere komplexe Datentypen verwenden.
Sie können für Typdeklarationen auch `str`, `float`, `bool` und viele andere komplexe Datentypen verwenden.
Mehrere davon werden wir in den nächsten Kapiteln erkunden.
## Die Reihenfolge ist wichtig
## Die Reihenfolge ist wichtig { #order-matters }
Wenn Sie *Pfadoperationen* erstellen, haben Sie manchmal einen fixen Pfad.
@@ -128,23 +128,23 @@ Sie können eine Pfadoperation auch nicht erneut definieren:
Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst übereinstimmt.
## Vordefinierte Parameterwerte
## Vordefinierte Parameterwerte { #predefined-values }
Wenn Sie eine *Pfadoperation* haben, welche einen *Pfad-Parameter* hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python <abbr title="Enumeration, oder kurz Enum – Aufzählung">`Enum`</abbr> verwenden.
Wenn Sie eine *Pfadoperation* haben, welche einen *Pfad-Parameter* hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python <abbr title="Enumeration">`Enum`</abbr> verwenden.
### Erstellen Sie eine `Enum`-Klasse
### Eine `Enum`-Klasse erstellen { #create-an-enum-class }
Importieren Sie `Enum` und erstellen Sie eine Unterklasse, die von `str` und `Enum` erbt.
Indem Sie von `str` erben, weiß die API Dokumentation, dass die Werte des Enums vom Typ `str` sein müssen, und wird in der Lage sein, korrekt zu rendern.
Indem Sie von `str` erben, weiß die API-Dokumentation, dass die Werte vom Typ `str` sein müssen, und wird in der Lage sein, korrekt zu rendern.
Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden:
{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
/// info
/// info | 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.
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder Enums)</a> gibt es in Python seit Version 3.4.
///
@@ -154,31 +154,31 @@ Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das
///
### Deklarieren Sie einen *Pfad-Parameter*
### Einen *Pfad-Parameter* deklarieren { #declare-a-path-parameter }
Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`):
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
### Testen Sie es in der API-Dokumentation
### Die API-Dokumentation testen { #check-the-docs }
Weil die erlaubten Werte für den *Pfad-Parameter* nun vordefiniert sind, kann die interaktive Dokumentation sie als Auswahl-Drop-Down anzeigen:
<img src="/img/tutorial/path-params/image03.png">
### Mit Python-*<abbr title="Enumeration – Aufzählung">Enums</abbr>* arbeiten
### Mit Python-*Enumerationen* arbeiten { #working-with-python-enumerations }
Der *Pfad-Parameter* wird ein *<abbr title="Member – Mitglied: Einer der möglichen Werte einer Enumeration">Member</abbr> eines Enums* sein.
Der *Pfad-Parameter* wird ein *<abbr title="Member – Mitglied: Einer der möglichen Werte einer Enumeration">Member</abbr> einer Enumeration* sein.
#### *Enum-Member* vergleichen
#### *Enumeration-Member* vergleichen { #compare-enumeration-members }
Sie können ihn mit einem Member Ihres Enums `ModelName` vergleichen:
Sie können ihn mit einem Member Ihrer Enumeration `ModelName` vergleichen:
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
#### *Enum-Wert* erhalten
#### *Enumerations-Wert* erhalten { #get-the-enumeration-value }
Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `ihr_enum_member.value`:
Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `your_enum_member.value`:
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
@@ -188,7 +188,7 @@ Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen
///
#### *Enum-Member* zurückgeben
#### *Enumeration-Member* zurückgeben { #return-enumeration-members }
Sie können *Enum-Member* in ihrer *Pfadoperation* zurückgeben, sogar verschachtelt in einem JSON-Body (z. B. als `dict`).
@@ -205,7 +205,7 @@ In Ihrem Client erhalten Sie eine JSON-Response, wie etwa:
}
```
## Pfad Parameter die Pfade enthalten
## Pfad-Parameter, die Pfade enthalten { #path-parameters-containing-paths }
Angenommen, Sie haben eine *Pfadoperation* mit einem Pfad `/files/{file_path}`.
@@ -213,7 +213,7 @@ Aber `file_path` soll selbst einen *Pfad* enthalten, etwa `home/johndoe/myfile.t
Sprich, die URL für diese Datei wäre etwas wie: `/files/home/johndoe/myfile.txt`.
### OpenAPI Unterstützung
### OpenAPI-Unterstützung { #openapi-support }
OpenAPI bietet nicht die Möglichkeit, dass ein *Pfad-Parameter* seinerseits einen *Pfad* enthalten kann, das würde zu Szenarios führen, die schwierig zu testen und zu definieren sind.
@@ -221,7 +221,7 @@ Trotzdem können Sie das in **FastAPI** tun, indem Sie eines der internen Tools
Die Dokumentation würde weiterhin funktionieren, allerdings wird nicht dokumentiert werden, dass der Parameter ein Pfad sein sollte.
### Pfad Konverter
### Pfad-Konverter { #path-convertor }
Mittels einer Option direkt von Starlette können Sie einen *Pfad-Parameter* deklarieren, der einen Pfad enthalten soll, indem Sie eine URL wie folgt definieren:
@@ -243,12 +243,12 @@ In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelte
///
## Zusammenfassung
## Zusammenfassung { #recap }
In **FastAPI** erhalten Sie mittels kurzer, intuitiver Typdeklarationen:
* Editor-Unterstützung: Fehlerprüfungen, Codevervollständigung, usw.
* Daten "<abbr title="Den String, der von einer HTTP Anfrage kommt, nach Python-Daten konvertieren">parsen</abbr>"
* Daten "<abbr title="Den String, der von einem HTTP-Request kommt, nach Python-Daten konvertieren">parsen</abbr>"
* Datenvalidierung
* API-Annotationen und automatische Dokumentation
@@ -0,0 +1,68 @@
# Query-Parameter-Modelle { #query-parameter-models }
Wenn Sie eine Gruppe von **Query-Parametern** haben, die miteinander in Beziehung stehen, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren.
Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und gleichzeitig Validierungen und Metadaten für alle Parameter auf einmal deklarieren. 😎
/// note | Hinweis
Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓
///
## Query-Parameter mit einem Pydantic-Modell { #query-parameters-with-a-pydantic-model }
Deklarieren Sie die benötigten **Query-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Query`:
{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *}
**FastAPI** wird die Daten für **jedes Feld** aus den **Query-Parametern** des <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> extrahieren und Ihnen das definierte Pydantic-Modell bereitstellen.
## Die Dokumentation testen { #check-the-docs }
Sie können die Query-Parameter in der Dokumentations-Oberfläche unter `/docs` einsehen:
<div class="screenshot">
<img src="/img/tutorial/query-param-models/image01.png">
</div>
## Zusätzliche Query-Parameter verbieten { #forbid-extra-query-parameters }
In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Query-Parameter, die Sie empfangen möchten, **beschränken**.
Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`:
{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
Wenn ein Client versucht, einige **zusätzliche** Daten in den **Query-Parametern** zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
Wenn der Client beispielsweise versucht, einen `tool` Query-Parameter mit dem Wert `plumbus` zu senden, wie:
```http
https://example.com/items/?limit=10&tool=plumbus
```
erhält er eine **Error-Response**, die ihm mitteilt, dass der Query-Parameter `tool` nicht erlaubt ist:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["query", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus"
}
]
}
```
## Zusammenfassung { #summary }
Sie können **Pydantic-Modelle** verwenden, um **Query-Parameter** in **FastAPI** zu deklarieren. 😎
/// tip | Tipp
Spoiler-Alarm: Sie können auch Pydantic-Modelle verwenden, um Cookies und Header zu deklarieren, aber darüber werden Sie später im Tutorial lesen. 🤫
///
@@ -1,69 +1,49 @@
# Query-Parameter und Stringvalidierung
# Query-Parameter und String-Validierungen { #query-parameters-and-string-validations }
**FastAPI** erlaubt es Ihnen, Ihre Parameter zusätzlich zu validieren, und zusätzliche Informationen hinzuzufügen.
**FastAPI** ermöglicht es Ihnen, zusätzliche Informationen und Validierungen für Ihre Parameter zu deklarieren.
Nehmen wir als Beispiel die folgende Anwendung:
Nehmen wir diese Anwendung als Beispiel:
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
Der Query-Parameter `q` hat den Typ `Union[str, None]` (oder `str | None` in Python 3.10), was bedeutet, er ist entweder ein `str` oder `None`. Der Defaultwert ist `None`, also weiß FastAPI, der Parameter ist nicht erforderlich.
Der Query-Parameter `q` hat den Typ `str | None`, das bedeutet, dass er vom Typ `str` sein kann, aber auch `None`, und tatsächlich ist der Defaultwert `None`, sodass FastAPI weiß, dass er nicht erforderlich ist.
/// note | Hinweis
FastAPI weiß nur dank des definierten Defaultwertes `=None`, dass der Wert von `q` nicht erforderlich ist
FastAPI erkennt, dass der Wert von `q` nicht erforderlich ist, aufgrund des Defaultwertes `= None`.
`Union[str, None]` hingegen erlaubt ihren Editor, Sie besser zu unterstützen und Fehler zu erkennen.
Die Verwendung von `str | None` ermöglicht es Ihrem Editor, Ihnen bessere Unterstützung zu bieten und Fehler zu erkennen.
///
## Zusätzliche Validierung
## Zusätzliche Validierung { #additional-validation }
Wir werden bewirken, dass, obwohl `q` optional ist, wenn es gegeben ist, **seine Länge 50 Zeichen nicht überschreitet**.
Wir werden sicherstellen, dass, obwohl `q` optional ist, wann immer es bereitgestellt wird, **seine Länge 50 Zeichen nicht überschreitet**.
### `Query` und `Annotated` importieren
### `Query` und `Annotated` importieren { #import-query-and-annotated }
Importieren Sie zuerst:
Um dies zu erreichen, importieren Sie zuerst:
* `Query` von `fastapi`
* `Annotated` von `typing` (oder von `typing_extensions` in Python unter 3.9)
* `Annotated` von `typing`
//// tab | Python 3.10+
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
In Python 3.9 oder darüber, ist `Annotated` Teil der Standardbibliothek, also können Sie es von `typing` importieren.
/// info | Info
```Python hl_lines="1 3"
{!> ../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
```
FastAPI hat Unterstützung für `Annotated` hinzugefügt (und begonnen, es zu empfehlen) in der Version 0.95.0.
////
Wenn Sie eine ältere Version haben, würden Sie Fehler erhalten, beim Versuch, `Annotated` zu verwenden.
//// tab | Python 3.8+
In Versionen unter Python 3.9 importieren Sie `Annotated` von `typing_extensions`.
Es wird bereits mit FastAPI installiert sein.
```Python hl_lines="3-4"
{!> ../../docs_src/query_params_str_validations/tutorial002_an.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.
Stellen Sie sicher, dass Sie [die FastAPI-Version aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}, auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden.
///
## `Annotated` im Typ des `q`-Parameters verwenden
## Verwenden von `Annotated` im Typ für den `q`-Parameter { #use-annotated-in-the-type-for-the-q-parameter }
Erinnern Sie sich, wie ich in [Einführung in Python-Typen](../python-types.md#typhinweise-mit-metadaten-annotationen){.internal-link target=_blank} sagte, dass Sie mittels `Annotated` Metadaten zu Ihren Parametern hinzufügen können?
Erinnern Sie sich, dass ich Ihnen zuvor in [Python-Typen-Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} gesagt habe, dass `Annotated` verwendet werden kann, um Metadaten zu Ihren Parametern hinzuzufügen?
Jetzt ist es an der Zeit, das mit FastAPI auszuprobieren. 🚀
Jetzt ist es soweit, dies mit FastAPI zu verwenden. 🚀
Wir hatten diese Typannotation:
@@ -83,7 +63,7 @@ q: Union[str, None] = None
////
Wir wrappen das nun in `Annotated`, sodass daraus wird:
Was wir tun werden, ist, dies mit `Annotated` zu wrappen, sodass es zu:
//// tab | Python 3.10+
@@ -101,101 +81,75 @@ q: Annotated[Union[str, None]] = None
////
Beide Versionen bedeuten dasselbe: `q` ist ein Parameter, der `str` oder `None` sein kann. Standardmäßig ist er `None`.
Beide dieser Versionen bedeuten dasselbe: `q` ist ein Parameter, der ein `str` oder `None` sein kann, und standardmäßig ist er `None`.
Wenden wir uns jetzt den spannenden Dingen zu. 🎉
Jetzt springen wir zu den spannenden Dingen. 🎉
## `Query` zu `Annotated` im `q`-Parameter hinzufügen
## `Query` zu `Annotated` im `q`-Parameter hinzufügen { #add-query-to-annotated-in-the-q-parameter }
Jetzt, da wir `Annotated` für unsere Metadaten deklariert haben, fügen Sie `Query` hinzu, und setzen Sie den Parameter `max_length` auf `50`:
Da wir nun `Annotated` haben, in das wir mehr Informationen (in diesem Fall einige zusätzliche Validierungen) einfügen können, fügen Sie `Query` innerhalb von `Annotated` hinzu und setzen Sie den Parameter `max_length` auf `50`:
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
Beachten Sie, dass der Defaultwert immer noch `None` ist, sodass der Parameter immer noch optional ist.
Beachten Sie, dass der Defaultwert weiterhin `None` ist, so dass der Parameter weiterhin optional ist.
Aber jetzt, mit `Query(max_length=50)` innerhalb von `Annotated`, sagen wir FastAPI, dass es diesen Wert aus den Query-Parametern extrahieren soll (das hätte es sowieso gemacht 🤷) und dass wir eine **zusätzliche Validierung** für diesen Wert haben wollen (darum machen wir das, um die zusätzliche Validierung zu bekommen). 😎
FastAPI wird nun:
* Die Daten **validieren** und sicherstellen, dass sie nicht länger als 50 Zeichen sind
* Dem Client einen **verständlichen Fehler** anzeigen, wenn die Daten ungültig sind
* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird)
## Alternativ (alt): `Query` als Defaultwert
Frühere Versionen von FastAPI (vor <abbr title="vor 2023-03">0.95.0</abbr>) benötigten `Query` als Defaultwert des Parameters, statt es innerhalb von `Annotated` unterzubringen. Die Chance ist groß, dass Sie Quellcode sehen, der das immer noch so macht, darum erkläre ich es Ihnen.
Aber jetzt, mit `Query(max_length=50)` innerhalb von `Annotated`, sagen wir FastAPI, dass wir eine **zusätzliche Validierung** für diesen Wert wünschen, wir wollen, dass er maximal 50 Zeichen hat. 😎
/// tip | Tipp
Verwenden Sie für neuen Code, und wann immer möglich, `Annotated`, wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰
Hier verwenden wir `Query()`, weil dies ein **Query-Parameter** ist. Später werden wir andere wie `Path()`, `Body()`, `Header()`, und `Cookie()` sehen, die auch dieselben Argumente wie `Query()` akzeptieren.
///
So würden Sie `Query()` als Defaultwert Ihres Funktionsparameters verwenden, den Parameter `max_length` auf 50 gesetzt:
FastAPI wird nun:
* Die Daten **validieren**, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt
* Einen **klaren Fehler** für den Client anzeigen, wenn die Daten ungültig sind
* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird)
## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value }
Frühere Versionen von FastAPI (vor <abbr title="vor 2023-03">0.95.0</abbr>) erforderten, dass Sie `Query` als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von `Annotated` zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklären.
/// tip | Tipp
Für neuen Code und wann immer es möglich ist, verwenden Sie `Annotated` wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰
///
So würden Sie `Query()` als den Defaultwert Ihres Funktionsparameters verwenden und den Parameter `max_length` auf 50 setzen:
{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
Da wir in diesem Fall (ohne die Verwendung von `Annotated`) den Parameter-Defaultwert `None` mit `Query()` ersetzen, müssen wir nun dessen Defaultwert mit dem Parameter `Query(default=None)` deklarieren. Das dient demselben Zweck, `None` als Defaultwert für den Funktionsparameter zu setzen (zumindest für FastAPI).
Da wir in diesem Fall (ohne die Verwendung von `Annotated`) den Defaultwert `None` in der Funktion durch `Query()` ersetzen müssen, müssen wir nun den Defaultwert mit dem Parameter `Query(default=None)` setzen, er erfüllt den gleichen Zweck, diesen Defaultwert zu definieren (zumindest für FastAPI).
Sprich:
```Python
q: Union[str, None] = Query(default=None)
```
... macht den Parameter optional, mit dem Defaultwert `None`, genauso wie:
```Python
q: Union[str, None] = None
```
Und in Python 3.10 und darüber macht:
Also:
```Python
q: str | None = Query(default=None)
```
... den Parameter optional, mit dem Defaultwert `None`, genauso wie:
... macht den Parameter optional mit einem Defaultwert von `None`, genauso wie:
```Python
q: str | None = None
```
Nur, dass die `Query`-Versionen den Parameter explizit als Query-Parameter deklarieren.
Aber die `Query`-Version deklariert ihn explizit als Query-Parameter.
/// info
Bedenken Sie, dass:
Dann können wir mehr Parameter an `Query` übergeben. In diesem Fall den `max_length`-Parameter, der auf Strings angewendet wird:
```Python
= None
q: str | None = Query(default=None, max_length=50)
```
oder:
Dies wird die Daten validieren, einen klaren Fehler anzeigen, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-*Pfadoperation* dokumentieren.
```Python
= Query(default=None)
```
### `Query` als Defaultwert oder in `Annotated` { #query-as-the-default-value-or-in-annotated }
der wichtigste Teil ist, um einen Parameter optional zu machen, da dieses `None` der Defaultwert ist, und das ist es, was diesen Parameter **nicht erforderlich** macht.
Beachten Sie, dass wenn Sie `Query` innerhalb von `Annotated` verwenden, Sie den `default`-Parameter für `Query` nicht verwenden dürfen.
Der Teil mit `Union[str, None]` erlaubt es Ihrem Editor, Sie besser zu unterstützen, aber er sagt FastAPI nicht, dass dieser Parameter optional ist.
///
Jetzt können wir `Query` weitere Parameter übergeben. Fangen wir mit dem `max_length` Parameter an, der auf Strings angewendet wird:
```Python
q: Union[str, None] = Query(default=None, max_length=50)
```
Das wird die Daten validieren, einen verständlichen Fehler ausgeben, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-*Pfadoperation* dokumentieren.
### `Query` als Defaultwert oder in `Annotated`
Bedenken Sie, dass wenn Sie `Query` innerhalb von `Annotated` benutzen, Sie den `default`-Parameter für `Query` nicht verwenden dürfen.
Setzen Sie stattdessen den Defaultwert des Funktionsparameters, sonst wäre es inkonsistent.
Setzen Sie stattdessen den tatsächlichen Defaultwert des Funktionsparameters. Andernfalls wäre es inkonsistent.
Zum Beispiel ist das nicht erlaubt:
@@ -203,7 +157,7 @@ Zum Beispiel ist das nicht erlaubt:
q: Annotated[str, Query(default="rick")] = "morty"
```
... denn es wird nicht klar, ob der Defaultwert `"rick"` oder `"morty"` sein soll.
... denn es ist nicht klar, ob der Defaultwert `"rick"` oder `"morty"` sein soll.
Sie würden also (bevorzugt) schreiben:
@@ -211,49 +165,49 @@ Sie würden also (bevorzugt) schreiben:
q: Annotated[str, Query()] = "rick"
```
In älterem Code werden Sie auch finden:
... oder in älteren Codebasen finden Sie:
```Python
q: str = Query(default="rick")
```
### Vorzüge von `Annotated`
### Vorzüge von `Annotated` { #advantages-of-annotated }
**Es wird empfohlen, `Annotated` zu verwenden**, statt des Defaultwertes im Funktionsparameter, das ist aus mehreren Gründen **besser**: 🤓
**Es wird empfohlen, `Annotated` zu verwenden**, anstelle des Defaultwertes in Funktionsparametern, es ist aus mehreren Gründen **besser**. 🤓
Der **Default**wert des **Funktionsparameters** ist der **tatsächliche Default**wert, das spielt generell intuitiver mit Python zusammen. 😌
Der **Default**wert des **Funktionsparameters** ist der **tatsächliche Default**wert, das ist in der Regel intuitiver mit Python. 😌
Sie können die Funktion ohne FastAPI an **anderen Stellen aufrufen**, und es wird **wie erwartet funktionieren**. Wenn es einen **erforderlichen** Parameter gibt (ohne Defaultwert), und Sie führen die Funktion ohne den benötigten Parameter aus, dann wird Ihr **Editor** Sie das mit einem Fehler wissen lassen, und **Python** wird sich auch beschweren.
Sie könnten **diese gleiche Funktion** in **anderen Stellen** ohne FastAPI **aufrufen**, und es würde **wie erwartet funktionieren**. Wenn es einen **erforderlichen** Parameter gibt (ohne Defaultwert), wird Ihr **Editor** Ihnen dies mit einem Fehler mitteilen, außerdem wird **Python** sich beschweren, wenn Sie es ausführen, ohne den erforderlichen Parameter zu übergeben.
Wenn Sie aber nicht `Annotated` benutzen und stattdessen die **(alte) Variante mit einem Defaultwert**, dann müssen Sie, wenn Sie die Funktion ohne FastAPI an **anderen Stellen** aufrufen, sich daran **erinnern**, die Argumente der Funktion zu übergeben, damit es richtig funktioniert. Ansonsten erhalten Sie unerwartete Werte (z. B. `QueryInfo` oder etwas Ähnliches, statt `str`). Ihr Editor kann ihnen nicht helfen, und Python wird die Funktion ohne Beschwerden ausführen, es sei denn, die Operationen innerhalb lösen einen Fehler aus.
Wenn Sie `Annotated` nicht verwenden und stattdessen die **(alte) Defaultwert-Stilform** verwenden, müssen Sie sich daran **erinnern**, die Argumente der Funktion zu übergeben, wenn Sie diese Funktion ohne FastAPI in **anderen Stellen** aufrufen. Ansonsten sind die Werte anders als erwartet (z. B. `QueryInfo` oder etwas Ähnliches statt `str`). Ihr Editor kann Ihnen nicht helfen, und Python wird die Funktion ohne Klagen ausführen und sich nur beschweren wenn die Operationen innerhalb auf einen Fehler stoßen.
Da `Annotated` mehrere Metadaten haben kann, können Sie dieselbe Funktion auch mit anderen Tools verwenden, wie etwa <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
Da `Annotated` mehr als eine Metadaten-Annotation haben kann, könnten Sie dieselbe Funktion sogar mit anderen Tools verwenden, wie z. B. <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
## Mehr Validierungen hinzufügen
## Mehr Validierungen hinzufügen { #add-more-validations }
Sie können auch einen Parameter `min_length` hinzufügen:
Sie können auch einen `min_length`-Parameter hinzufügen:
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
## Reguläre Ausdrücke hinzufügen
## Reguläre Ausdrücke hinzufügen { #add-regular-expressions }
Sie können einen <abbr title="Ein regulärer Ausdruck, auch regex oder regexp genannt, ist eine Zeichensequenz, die ein Suchmuster für Strings definiert.">Regulären Ausdruck</abbr> `pattern` definieren, mit dem der Parameter übereinstimmen muss:
Sie können einen <abbr title="Ein regulärer Ausdruck, regex oder regexp genannt, ist eine Sequenz von Zeichen, die ein Suchmuster für Zeichenfolgen definiert.">regulären Ausdruck</abbr> `pattern` definieren, mit dem der Parameter übereinstimmen muss:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
Dieses bestimmte reguläre Suchmuster prüft, ob der erhaltene Parameter-Wert:
Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhaltene Parameterwert:
* `^`: mit den nachfolgenden Zeichen startet, keine Zeichen davor hat.
* `^`: mit den nachfolgenden Zeichen beginnt, keine Zeichen davor hat.
* `fixedquery`: den exakten Text `fixedquery` hat.
* `$`: danach endet, keine weiteren Zeichen hat als `fixedquery`.
* `$`: dort endet, keine weiteren Zeichen nach `fixedquery` hat.
Wenn Sie sich verloren fühlen bei all diesen **„Regulärer Ausdruck“**-Konzepten, keine Sorge. Reguläre Ausdrücke sind für viele Menschen ein schwieriges Thema. Sie können auch ohne reguläre Ausdrücke eine ganze Menge machen.
Wenn Sie sich mit all diesen **„regulärer Ausdruck“**-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen.
Aber wenn Sie sie brauchen und sie lernen, wissen Sie, dass Sie sie bereits direkt in **FastAPI** verwenden können.
Aber nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen.
### Pydantic v1 `regex` statt `pattern`
### Pydantic v1 `regex` statt `pattern` { #pydantic-v1-regex-instead-of-pattern }
Vor Pydantic Version 2 und vor FastAPI Version 0.100.0, war der Name des Parameters `regex` statt `pattern`, aber das ist jetzt <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr>.
Vor Pydantic Version 2 und FastAPI 0.100.0, hieß der Parameter `regex` statt `pattern`, aber das ist jetzt obsolet.
Sie könnten immer noch Code sehen, der den alten Namen verwendet:
@@ -263,25 +217,25 @@ Sie könnten immer noch Code sehen, der den alten Namen verwendet:
////
Beachten Sie aber, dass das deprecated ist, und zum neuen Namen `pattern` geändert werden sollte. 🤓
Beachten Sie aber, dass das obsolet ist und auf den neuen Parameter `pattern` aktualisiert werden sollte. 🤓
## Defaultwerte
## Defaultwerte { #default-values }
Sie können natürlich andere Defaultwerte als `None` verwenden.
Natürlich können Sie Defaultwerte verwenden, die nicht `None` sind.
Beispielsweise könnten Sie den `q` Query-Parameter so deklarieren, dass er eine `min_length` von `3` hat, und den Defaultwert `"fixedquery"`:
Nehmen wir an, Sie möchten, dass der `q` Query-Parameter eine `min_length` von `3` hat und einen Defaultwert von `"fixedquery"`:
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
/// note | Hinweis
Ein Parameter ist optional (nicht erforderlich), wenn er irgendeinen Defaultwert, auch `None`, hat.
Ein Defaultwert irgendeines Typs, einschließlich `None`, macht den Parameter optional (nicht erforderlich).
///
## Erforderliche Parameter
## Erforderliche Parameter { #required-parameters }
Wenn wir keine Validierungen oder Metadaten haben, können wir den `q` Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie in:
Wenn wir keine weiteren Validierungen oder Metadaten deklarieren müssen, können wir den `q` Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie:
```Python
q: str
@@ -290,56 +244,32 @@ q: str
statt:
```Python
q: Union[str, None] = None
q: str | None = None
```
Aber jetzt deklarieren wir den Parameter mit `Query`, wie in:
//// tab | Annotiert
Aber jetzt deklarieren wir es mit `Query`, zum Beispiel so:
```Python
q: Annotated[Union[str, None], Query(min_length=3)] = None
q: Annotated[str | None, Query(min_length=3)] = None
```
////
//// tab | Nicht annotiert
```Python
q: Union[str, None] = Query(default=None, min_length=3)
```
////
Wenn Sie einen Parameter erforderlich machen wollen, während Sie `Query` verwenden, deklarieren Sie ebenfalls einfach keinen Defaultwert:
Wenn Sie einen Wert als erforderlich deklarieren müssen, während Sie `Query` verwenden, deklarieren Sie einfach keinen Defaultwert:
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
### Erforderlich, kann `None` sein
### Erforderlich, kann `None` sein { #required-can-be-none }
Sie können deklarieren, dass ein Parameter `None` akzeptiert, aber dennoch erforderlich ist. Das zwingt Clients, den Wert zu senden, selbst wenn er `None` ist.
Sie können deklarieren, dass ein Parameter `None` akzeptieren kann, aber trotzdem erforderlich ist. Dadurch müssten Clients den Wert senden, selbst wenn der Wert `None` ist.
Um das zu machen, deklarieren Sie, dass `None` ein gültiger Typ ist, aber verwenden Sie dennoch `...` als Default:
Um das zu tun, können Sie deklarieren, dass `None` ein gültiger Typ ist, einfach indem Sie keinen Defaultwert deklarieren:
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
/// tip | Tipp
## Query-Parameter-Liste / Mehrere Werte { #query-parameter-list-multiple-values }
Pydantic, welches die gesamte Datenvalidierung und Serialisierung in FastAPI antreibt, hat ein spezielles Verhalten, wenn Sie `Optional` oder `Union[Something, None]` ohne Defaultwert verwenden, Sie können mehr darüber in der Pydantic-Dokumentation unter <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required fields</a> erfahren.
Wenn Sie einen Query-Parameter explizit mit `Query` definieren, können Sie ihn auch so deklarieren, dass er eine Liste von Werten empfängt, oder anders gesagt, dass er mehrere Werte empfangen kann.
///
/// tip | Tipp
Denken Sie daran, dass Sie in den meisten Fällen, wenn etwas erforderlich ist, einfach den Defaultwert weglassen können. Sie müssen also normalerweise `...` nicht verwenden.
///
## Query-Parameter-Liste / Mehrere Werte
Wenn Sie einen Query-Parameter explizit mit `Query` auszeichnen, können Sie ihn auch eine Liste von Werten empfangen lassen, oder anders gesagt, mehrere Werte.
Um zum Beispiel einen Query-Parameter `q` zu deklarieren, der mehrere Male in der URL vorkommen kann, schreiben Sie:
Um zum Beispiel einen Query-Parameter `q` zu deklarieren, der mehrmals in der URL vorkommen kann, schreiben Sie:
{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
@@ -349,9 +279,9 @@ Dann, mit einer URL wie:
http://localhost:8000/items/?q=foo&q=bar
```
bekommen Sie alle `q`-*Query-Parameter*-Werte (`foo` und `bar`) in einer Python-Liste – `list` – in ihrer *Pfadoperation-Funktion*, im Funktionsparameter `q`, überreicht.
würden Sie die mehreren `q`-*Query-Parameter*-Werte (`foo` und `bar`) in einer Python-`list` in Ihrer *Pfadoperation-Funktion* im *Funktionsparameter* `q` erhalten.
Die Response für diese URL wäre also:
So wäre die <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> zu dieser URL:
```JSON
{
@@ -364,27 +294,27 @@ Die Response für diese URL wäre also:
/// tip | Tipp
Um einen Query-Parameter vom Typ `list` zu deklarieren, wie im Beispiel oben, müssen Sie explizit `Query` verwenden, sonst würde der Parameter als Requestbody interpretiert werden.
Um einen Query-Parameter mit einem Typ `list` zu deklarieren, wie im obigen Beispiel, müssen Sie explizit `Query` verwenden, da er andernfalls als <abbr title="Anfragekörper">Requestbody</abbr> interpretiert würde.
///
Die interaktive API-Dokumentation wird entsprechend aktualisiert und erlaubt jetzt mehrere Werte.
Die interaktive API-Dokumentation wird entsprechend aktualisiert, um mehrere Werte zu erlauben:
<img src="/img/tutorial/query-params-str-validations/image02.png">
### Query-Parameter-Liste / Mehrere Werte mit Defaults
### Query-Parameter-Liste / Mehrere Werte mit Defaults { #query-parameter-list-multiple-values-with-defaults }
Und Sie können auch eine Default-`list`e von Werten definieren, wenn keine übergeben werden:
Sie können auch eine Default-`list` von Werten definieren, wenn keine bereitgestellt werden:
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
Wenn Sie auf:
Wenn Sie zu:
```
http://localhost:8000/items/
```
gehen, wird der Default für `q` verwendet: `["foo", "bar"]`, und als Response erhalten Sie:
gehen, wird der Default für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein:
```JSON
{
@@ -395,9 +325,9 @@ gehen, wird der Default für `q` verwendet: `["foo", "bar"]`, und als Response e
}
```
#### `list` alleine verwenden
#### Nur `list` verwenden { #using-just-list }
Sie können auch `list` direkt verwenden, anstelle von `List[str]` (oder `list[str]` in Python 3.9+):
Sie können auch `list` direkt verwenden, anstelle von `list[str]`:
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
@@ -405,35 +335,35 @@ Sie können auch `list` direkt verwenden, anstelle von `List[str]` (oder `list[s
Beachten Sie, dass FastAPI in diesem Fall den Inhalt der Liste nicht überprüft.
Zum Beispiel würde `List[int]` überprüfen (und dokumentieren) dass die Liste Ganzzahlen enthält. `list` alleine macht das nicht.
Zum Beispiel würde `list[int]` überprüfen (und dokumentieren), dass der Inhalt der Liste Ganzzahlen sind. Aber `list` alleine würde das nicht.
///
## Deklarieren von mehr Metadaten
## Mehr Metadaten deklarieren { #declare-more-metadata }
Sie können mehr Informationen zum Parameter hinzufügen.
Sie können mehr Informationen über den Parameter hinzufügen.
Diese Informationen werden zur generierten OpenAPI hinzugefügt, und von den Dokumentations-Oberflächen und von externen Tools verwendet.
Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dokumentationsoberflächen und externen Tools verwendet.
/// note | Hinweis
Beachten Sie, dass verschiedene Tools OpenAPI möglicherweise unterschiedlich gut unterstützen.
Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben.
Einige könnten noch nicht alle zusätzlichen Informationen anzeigen, die Sie deklariert haben, obwohl in den meisten Fällen geplant ist, das fehlende Feature zu implementieren.
Einige davon könnten noch nicht alle zusätzlichen Informationen anzuzeigen, die Sie erklärten, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist.
///
Sie können einen Titel hinzufügen – `title`:
Sie können einen `title` hinzufügen:
{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
Und eine Beschreibung – `description`:
Und eine `description`:
{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
## Alias-Parameter
## Alias-Parameter { #alias-parameters }
Stellen Sie sich vor, der Parameter soll `item-query` sein.
Stellen Sie sich vor, Sie möchten, dass der Parameter `item-query` ist.
Wie in:
@@ -443,37 +373,99 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
Aber `item-query` ist kein gültiger Name für eine Variable in Python.
Am ähnlichsten wäre `item_query`.
Der am ähnlichsten wäre `item_query`.
Aber Sie möchten dennoch exakt `item-query` verwenden.
Aber Sie benötigen dennoch, dass er genau `item-query` ist ...
Dann können Sie einen `alias` deklarieren, und dieser Alias wird verwendet, um den Parameter-Wert zu finden:
Dann können Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um den Parameterwert zu finden:
{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
## Parameter als deprecated ausweisen
## Parameter als deprecatet ausweisen { #deprecating-parameters }
Nehmen wir an, Sie mögen diesen Parameter nicht mehr.
Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr.
Sie müssen ihn eine Weile dort belassen, weil Clients ihn benutzen, aber Sie möchten, dass die Dokumentation klar anzeigt, dass er <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> ist.
Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> anzeigt.
In diesem Fall fügen Sie den Parameter `deprecated=True` zu `Query` hinzu.
Dann übergeben Sie den Parameter `deprecated=True` an `Query`:
{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
Die Dokumentation wird das so anzeigen:
Die Dokumentation wird es so anzeigen:
<img src="/img/tutorial/query-params-str-validations/image01.png">
## Parameter von OpenAPI ausschließen
## Parameter von OpenAPI ausschließen { #exclude-parameters-from-openapi }
Um einen Query-Parameter vom generierten OpenAPI-Schema auszuschließen (und daher von automatischen Dokumentations-Systemen), setzen Sie den Parameter `include_in_schema` in `Query` auf `False`.
Um einen Query-Parameter aus dem generierten OpenAPI-Schema auszuschließen (und somit aus den automatischen Dokumentationssystemen), setzen Sie den Parameter `include_in_schema` von `Query` auf `False`:
{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
## Zusammenfassung
## Benutzerdefinierte Validierung { #custom-validation }
Sie können zusätzliche Validierungen und Metadaten zu ihren Parametern hinzufügen.
Es kann Fälle geben, in denen Sie eine **benutzerdefinierte Validierung** durchführen müssen, die nicht mit den oben gezeigten Parametern durchgeführt werden kann.
In diesen Fällen können Sie eine **benutzerdefinierte Validierungsfunktion** verwenden, die nach der normalen Validierung angewendet wird (z. B. nach der Validierung, dass der Wert ein `str` ist).
Sie können dies mit <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">Pydantic's `AfterValidator`</a> innerhalb von `Annotated` erreichen.
/// tip | Tipp
Pydantic unterstützt auch <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> und andere. 🤓
///
Zum Beispiel überprüft dieser benutzerdefinierte Validator, ob die Artikel-ID mit `isbn-` für eine <abbr title="ISBN bedeutet Internationale Standardbuchnummer">ISBN</abbr>-Buchnummer oder mit `imdb-` für eine <abbr title="IMDB (Internet Movie Database) ist eine Website mit Informationen über Filme">IMDB</abbr>-Film-URL-ID beginnt:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
/// info | Info
Dies ist verfügbar seit Pydantic Version 2 oder höher. 😎
///
/// tip | Tipp
Wenn Sie irgendeine Art von Validierung durchführen müssen, die eine Kommunikation mit einer **externen Komponente** erfordert, wie z. B. einer Datenbank oder einer anderen API, sollten Sie stattdessen **FastAPI-Abhängigkeiten** verwenden. Sie werden diese später kennenlernen.
Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit denselben **Daten** überprüft werden können, die im Request bereitgestellt werden.
///
### Dieses Codebeispiel verstehen { #understand-that-code }
Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer Funktion innerhalb von `Annotated`**. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸
---
Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details.
#### Zeichenkette mit `value.startswith()` { #string-with-value-startswith }
Haben Sie bemerkt? Eine Zeichenkette mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
#### Ein zufälliges Item { #a-random-item }
Mit `data.items()` erhalten wir ein <abbr title="Etwas, das man mit einer for-Schleife durchlaufen kann, wie eine Liste, Set, usw.">iterierbares Objekt</abbr> mit Tupeln, die Schlüssel und Wert für jedes <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr>-Element enthalten.
Wir konvertieren dieses iterierbare Objekt mit `list(data.items())` in eine richtige `list`.
Dann können wir mit `random.choice()` einen **zufälligen Wert** aus der Liste erhalten, also bekommen wir ein Tuple mit `(id, name)`. Es wird etwas wie `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` sein.
Dann **weisen wir diese beiden Werte** des Tupels den Variablen `id` und `name` zu.
Wenn der Benutzer also keine Artikel-ID bereitgestellt hat, erhält er trotzdem einen zufälligen Vorschlag.
... wir tun all dies in einer **einzelnen einfachen Zeile**. 🤯 Lieben Sie nicht auch Python? 🐍
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
## Zusammenfassung { #recap }
Sie können zusätzliche Validierungen und Metadaten für Ihre Parameter deklarieren.
Allgemeine Validierungen und Metadaten:
@@ -482,12 +474,14 @@ Allgemeine Validierungen und Metadaten:
* `description`
* `deprecated`
Validierungen spezifisch für Strings:
Validierungen, die spezifisch für Strings sind:
* `min_length`
* `max_length`
* `pattern`
In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für Strings hinzufügen.
Benutzerdefinierte Validierungen mit `AfterValidator`.
In den nächsten Kapiteln sehen wir, wie man Validierungen für andere Typen hinzufügt, etwa für Zahlen.
In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für `str`-Werte deklarieren.
Sehen Sie sich die nächsten Kapitel an, um zu erfahren, wie Sie Validierungen für andere Typen, wie z. B. Zahlen, deklarieren.
+18 -18
View File
@@ -1,10 +1,10 @@
# Query-Parameter
# Query-Parameter { #query-parameters }
Wenn Sie in ihrer Funktion Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert.
Wenn Sie in Ihrer Funktion andere Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert.
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
Query-Parameter (Deutsch: Abfrage-Parameter) sind die Schlüssel-Wert-Paare, die nach dem `?` in einer URL aufgelistet sind, getrennt durch `&`-Zeichen.
Die <abbr title="Abfrage">Query</abbr> ist die Menge von Schlüssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind.
Zum Beispiel sind in der URL:
@@ -19,18 +19,18 @@ http://127.0.0.1:8000/items/?skip=0&limit=10
Da sie Teil der URL sind, sind sie „naturgemäß“ Strings.
Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), werden sie zu diesem Typ konvertiert, und gegen diesen validiert.
Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), werden sie zu diesem Typ konvertiert und gegen diesen validiert.
Die gleichen Prozesse, die für Pfad-Parameter stattfinden, werden auch auf Query-Parameter angewendet:
Die gleichen Prozesse, die für Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet:
* Editor Unterstützung (natürlich)
* <abbr title="Konvertieren des Strings, der von einer HTTP-Anfrage kommt, in Python-Daten">„Parsen“</abbr> der Daten
* Daten-<abbr title="Konvertieren des Strings, der von einem HTTP-Request kommt, in Python-Daten">„Parsen“</abbr>
* Datenvalidierung
* Automatische Dokumentation
## Defaultwerte
## Defaultwerte { #defaults }
Da Query-Parameter nicht ein festgelegter Teil des Pfades sind, können sie optional sein und Defaultwerte haben.
Da Query-Parameter kein fester Teil eines Pfades sind, können sie optional sein und Defaultwerte haben.
Im obigen Beispiel haben sie die Defaultwerte `skip=0` und `limit=10`.
@@ -52,28 +52,28 @@ Aber wenn Sie zum Beispiel zu:
http://127.0.0.1:8000/items/?skip=20
```
gehen, werden die Parameter-Werte Ihrer Funktion sein:
gehen, werden die Parameterwerte Ihrer Funktion sein:
* `skip=20`: da Sie das in der URL gesetzt haben
* `limit=10`: weil das der Defaultwert ist
## Optionale Parameter
## Optionale Parameter { #optional-parameters }
Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem Sie deren Defaultwert auf `None` setzen:
{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
In diesem Fall wird der Funktionsparameter `q` optional, und standardmäßig `None` sein.
In diesem Fall wird der Funktionsparameter `q` optional und standardmäßig `None` sein.
/// check
/// check | Testen
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
## Query-Parameter Typkonvertierung { #query-parameter-type-conversion }
Sie können auch `bool`-Typen deklarieren und sie werden konvertiert:
Sie können auch `bool`-Typen deklarieren, und sie werden konvertiert:
{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
@@ -109,9 +109,9 @@ http://127.0.0.1:8000/items/foo?short=yes
gehen, oder zu irgendeiner anderen Variante der Groß-/Kleinschreibung (Alles groß, Anfangsbuchstabe groß, usw.), dann wird Ihre Funktion den Parameter `short` mit dem `bool`-Wert `True` sehen, ansonsten mit dem Wert `False`.
## Mehrere Pfad- und Query-Parameter
## Mehrere Pfad- und Query-Parameter { #multiple-path-and-query-parameters }
Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, was welches ist.
Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, welches welcher ist.
Und Sie müssen sie auch nicht in einer spezifischen Reihenfolge deklarieren.
@@ -119,7 +119,7 @@ Parameter werden anhand ihres Namens erkannt:
{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
## Erforderliche Query-Parameter
## Erforderliche Query-Parameter { #required-query-parameters }
Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (Bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich.
@@ -182,6 +182,6 @@ In diesem Fall gibt es drei Query-Parameter:
/// 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}.
Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#predefined-values){.internal-link target=_blank}.
///
+34 -30
View File
@@ -1,40 +1,44 @@
# Dateien im Request
# Dateien im Request { #request-files }
Mit `File` können sie vom Client hochzuladende Dateien definieren.
Sie können Dateien, die vom Client hochgeladen werden, mithilfe von `File` definieren.
/// info
/// info | 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>.
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Z. B. `pip install python-multipart`.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann das Paket installieren, zum Beispiel:
Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden.
```console
$ pip install python-multipart
```
Das liegt daran, dass hochgeladene Dateien als „Formulardaten“ gesendet werden.
///
## `File` importieren
## `File` importieren { #import-file }
Importieren Sie `File` und `UploadFile` von `fastapi`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
## `File`-Parameter definieren
## `File`-Parameter definieren { #define-file-parameters }
Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
/// info
/// info | 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
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.
Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body (JSON)-Parameter interpretiert werden würden.
///
@@ -46,7 +50,7 @@ Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbei
Aber es gibt viele Fälle, in denen Sie davon profitieren, `UploadFile` zu verwenden.
## Datei-Parameter mit `UploadFile`
## Datei-Parameter mit `UploadFile` { #file-parameters-with-uploadfile }
Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`:
@@ -55,20 +59,20 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`:
`UploadFile` zu verwenden, hat mehrere Vorzüge gegenüber `bytes`:
* Sie müssen `File()` nicht als Parameter-Defaultwert verwenden.
* Es wird eine <abbr title='Aufgespult, Warteschlangenartig'>„Spool“</abbr>-Datei verwendet:
* Es wird eine <abbr title="warteschlangenartig">„gespoolte“</abbr> Datei verwendet:
* Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird.
* Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen.
* Sie können Metadaten aus der hochgeladenen Datei auslesen.
* Es hat eine <abbr title="dateiartig"><a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a></abbr> `async`hrone Schnittstelle.
* Es stellt ein tatsächliches Python-<abbr title="Warteschlangenartige, temporäre Datei"><a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a></abbr>-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten.
* Es hat eine <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">dateiartige</a> `async`hrone Schnittstelle.
* Es stellt ein tatsächliches Python-<a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a>-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten.
### `UploadFile`
### `UploadFile` { #uploadfile }
`UploadFile` hat die folgenden Attribute:
* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `meinbild.jpg`).
* `content_type`: Ein `str` mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. `image/jpeg`).
* `file`: Ein <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (ein <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten.
* `file`: Ein <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (ein <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">dateiartiges</a> Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten.
`UploadFile` hat die folgenden `async`hronen Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird).
@@ -79,7 +83,7 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`:
* Das ist besonders dann nützlich, wenn Sie `await myfile.read()` einmal ausführen und dann diese Inhalte erneut auslesen müssen.
* `close()`: Schließt die Datei.
Da alle diese Methoden `async`hron sind, müssen Sie sie `await`en („erwarten“).
Da alle diese Methoden `async`hron sind, müssen Sie sie „await“en („erwarten“).
Zum Beispiel können Sie innerhalb einer `async` *Pfadoperation-Funktion* den Inhalt wie folgt auslesen:
@@ -105,9 +109,9 @@ Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden i
///
## Was sind „Formulardaten“
## Was sind „Formulardaten“ { #what-is-form-data }
HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodierung zum Server, welche sich von JSON unterscheidet.
Der Weg, wie HTML-Formulare (`<form></form>`) die Daten zum Server senden, verwendet normalerweise eine „spezielle“ Kodierung für diese Daten. Diese unterscheidet sich von JSON.
**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
@@ -117,31 +121,31 @@ Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem <
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.
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 Sie mehr über diese Kodierungen und Formularfelder 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-Entwicklernetzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
///
/// 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.
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 <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> den Body mittels `multipart/form-data` statt `application/json` kodiert.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Optionaler Datei-Upload
## Optionaler Datei-Upload { #optional-file-upload }
Sie können eine Datei optional machen, indem Sie Standard-Typannotationen verwenden und den Defaultwert auf `None` setzen:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
## `UploadFile` mit zusätzlichen Metadaten
## `UploadFile` mit zusätzlichen Metadaten { #uploadfile-with-additional-metadata }
Sie können auch `File()` zusammen mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen:
Sie können auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
## Mehrere Datei-Uploads
## Mehrere Datei-Uploads { #multiple-file-uploads }
Es ist auch möglich, mehrere Dateien gleichzeitig hochzuladen.
@@ -151,22 +155,22 @@ Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s:
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
Sie erhalten, wie deklariert, eine `list`e von `bytes` oder `UploadFile`s.
Sie erhalten, wie deklariert, eine `list` von `bytes` oder `UploadFile`s.
/// note | Technische Details
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.
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Responses</abbr> kommen aber direkt von Starlette.
///
### Mehrere Datei-Uploads mit zusätzlichen Metadaten
### Mehrere Datei-Uploads mit zusätzlichen Metadaten { #multiple-file-uploads-with-additional-metadata }
Und so wie zuvor können Sie `File()` verwenden, um zusätzliche Parameter zu setzen, sogar für `UploadFile`:
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
## Zusammenfassung
## Zusammenfassung { #recap }
Verwenden Sie `File`, `bytes` und `UploadFile`, um hochladbare Dateien im Request zu deklarieren, die als Formulardaten gesendet werden.
@@ -0,0 +1,78 @@
# Formularmodelle { #form-models }
Sie können **Pydantic-Modelle** verwenden, um **Formularfelder** in FastAPI zu deklarieren.
/// info | Info
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann installieren, zum Beispiel:
```console
$ pip install python-multipart
```
///
/// note | Hinweis
Dies wird seit FastAPI Version `0.113.0` unterstützt. 🤓
///
## Pydantic-Modelle für Formulare { #pydantic-models-for-forms }
Sie müssen nur ein **Pydantic-Modell** mit den Feldern deklarieren, die Sie als **Formularfelder** erhalten möchten, und dann den Parameter als `Form` deklarieren:
{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
**FastAPI** wird die Daten für **jedes Feld** aus den **Formulardaten** im <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell übergeben.
## Die Dokumentation testen { #check-the-docs }
Sie können dies in der Dokumentations-UI unter `/docs` testen:
<div class="screenshot">
<img src="/img/tutorial/request-form-models/image01.png">
</div>
## Zusätzliche Formularfelder verbieten { #forbid-extra-form-fields }
In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Formularfelder auf nur diejenigen beschränken, die im Pydantic-Modell deklariert sind, und jegliche **zusätzlichen** Felder **verbieten**.
/// note | Hinweis
Dies wird seit FastAPI Version `0.114.0` unterstützt. 🤓
///
Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`:
{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
Wenn ein Client versucht, einige zusätzliche Daten zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
Zum Beispiel, wenn der Client versucht, folgende Formularfelder zu senden:
* `username`: `Rick`
* `password`: `Portal Gun`
* `extra`: `Mr. Poopybutthole`
erhält er eine Error-Response, die ihm mitteilt, dass das Feld `extra` nicht erlaubt ist:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["body", "extra"],
"msg": "Extra inputs are not permitted",
"input": "Mr. Poopybutthole"
}
]
}
```
## Zusammenfassung { #summary }
Sie können Pydantic-Modelle verwenden, um Formularfelder in FastAPI zu deklarieren. 😎
@@ -1,22 +1,26 @@
# Formulardaten und Dateien im Request
# Formulardaten und Dateien im Request { #request-forms-and-files }
Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren.
/// info
/// info | 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>.
Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Z. B. `pip install python-multipart`.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, diese aktivieren und es dann installieren, z. B.:
```console
$ pip install python-multipart
```
///
## `File` und `Form` importieren
## `File` und `Form` importieren { #import-file-and-form }
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
## `File` und `Form`-Parameter definieren
## `File` und `Form`-Parameter definieren { #define-file-and-form-parameters }
Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` und `Query` machen würden:
Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` oder `Query` machen würden:
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
@@ -26,12 +30,12 @@ Und Sie können einige der Dateien als `bytes` und einige als `UploadFile` dekla
/// 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.
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht auch `Body`-Felder deklarieren, die Sie als JSON erwarten, da der Body des <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> mittels `multipart/form-data` statt `application/json` kodiert sein wird.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Zusammenfassung
## Zusammenfassung { #recap }
Verwenden Sie `File` und `Form` zusammen, wenn Sie Daten und Dateien zusammen im selben Request empfangen müssen.
+19 -15
View File
@@ -1,34 +1,38 @@
# Formulardaten
# Formulardaten { #form-data }
Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden.
/// info
/// info | 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>.
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Z. B. `pip install python-multipart`.
Erstellen Sie unbedingt eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie diese und installieren Sie dann das Paket, zum Beispiel:
```console
$ pip install python-multipart
```
///
## `Form` importieren
## `Form` importieren { #import-form }
Importieren Sie `Form` von `fastapi`:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
## `Form`-Parameter definieren
## `Form`-Parameter definieren { #define-form-parameters }
Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen würden:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
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.
Zum Beispiel stellt eine der Möglichkeiten, die OAuth2-Spezifikation zu verwenden (genannt „password flow“), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden.
Die <abbr title="Specification – Spezifikation">Spec</abbr> erfordert, dass die Felder exakt `username` und `password` genannt werden und als Formularfelder, nicht JSON, gesendet werden.
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
/// info | Info
`Form` ist eine Klasse, die direkt von `Body` erbt.
@@ -36,34 +40,34 @@ Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (u
/// 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.
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“
## Über „Formularfelder“ { #about-form-fields }
HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodierung zum Server, welche sich von JSON unterscheidet.
HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodierung zum Server, die sich von JSON unterscheidet.
**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.
Daten aus Formularen werden normalerweise mit dem <abbr title="Medientyp">„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
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.
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 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-Entwicklernetzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
///
/// 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.
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 <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert.
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
///
## Zusammenfassung
## Zusammenfassung { #recap }
Verwenden Sie `Form`, um Eingabe-Parameter für Formulardaten zu deklarieren.
+51 -42
View File
@@ -1,6 +1,6 @@
# Responsemodell – Rückgabetyp
# Responsemodell – Rückgabetyp { #response-model-return-type }
Sie können den Typ der <abbr title="Response – Antwort: Daten, die zum anfragenden Client zurückgeschickt werden">Response</abbr> deklarieren, indem Sie den **Rückgabetyp** der *Pfadoperation* annotieren.
Sie können den Typ der <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> deklarieren, indem Sie den **Rückgabetyp** der *Pfadoperation* annotieren.
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.
@@ -9,7 +9,7 @@ Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten
FastAPI wird diesen Rückgabetyp verwenden, um:
* Die zurückzugebenden Daten zu **validieren**.
* Wenn die Daten ungültig sind (Sie haben z. B. ein Feld vergessen), bedeutet das, *Ihr* Anwendungscode ist fehlerhaft, er gibt nicht zurück, was er sollte, und daher wird ein <abbr title="Server-Fehler">Server-Error</abbr> ausgegeben, statt falscher Daten. So können Sie und ihre Clients sicher sein, dass diese die erwarteten Daten, in der richtigen Form erhalten.
* Wenn die Daten ungültig sind (Sie haben z. B. ein Feld vergessen), bedeutet das, *Ihr* Anwendungscode ist fehlerhaft, er gibt nicht zurück, was er sollte, und daher wird ein <abbr title="Server-Fehler">Server-Error</abbr> ausgegeben, statt falscher Daten. So können Sie und Ihre Clients sicher sein, dass diese die erwarteten Daten, in der richtigen Form erhalten.
* In der OpenAPI *Pfadoperation* ein **JSON-Schema** für die Response hinzuzufügen.
* Dieses wird von der **automatischen Dokumentation** verwendet.
* Es wird auch von automatisch Client-Code-generierenden Tools verwendet.
@@ -19,11 +19,11 @@ Aber am wichtigsten:
* Es wird die Ausgabedaten auf das **limitieren und filtern**, was im Rückgabetyp definiert ist.
* Das ist insbesondere für die **Sicherheit** wichtig, mehr dazu unten.
## `response_model`-Parameter
## `response_model`-Parameter { #response-model-parameter }
Es gibt Fälle, da möchten oder müssen Sie Daten zurückgeben, die nicht genau dem entsprechen, was der Typ deklariert.
Zum Beispiel könnten Sie **ein Dict zurückgeben** wollen, oder ein Datenbank-Objekt, aber **es als Pydantic-Modell deklarieren**. Auf diese Weise übernimmt das Pydantic-Modell alle Datendokumentation, -validierung, usw. für das Objekt, welches Sie zurückgeben (z. B. ein Dict oder ein Datenbank-Objekt).
Zum Beispiel könnten Sie **ein Dictionary zurückgeben** wollen, oder ein Datenbank-Objekt, aber **es als Pydantic-Modell deklarieren**. Auf diese Weise übernimmt das Pydantic-Modell alle Datendokumentation, -validierung, usw. für das Objekt, welches Sie zurückgeben (z. B. ein Dictionary oder ein Datenbank-Objekt).
Würden Sie eine hierfür eine Rückgabetyp-Annotation verwenden, dann würden Tools und Editoren (korrekterweise) Fehler ausgeben, die Ihnen sagen, dass Ihre Funktion einen Typ zurückgibt (z. B. ein Dict), der sich unterscheidet von dem, was Sie deklariert haben (z. B. ein Pydantic-Modell).
@@ -41,7 +41,7 @@ Sie können `response_model` in jeder möglichen *Pfadoperation* verwenden:
/// 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.
Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body.
///
@@ -51,32 +51,41 @@ FastAPI wird dieses `response_model` nehmen, um die Daten zu dokumentieren, vali
/// 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.
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
### `response_model`-Priorität { #response-model-priority }
Wenn sowohl Rückgabetyp als auch `response_model` deklariert sind, hat `response_model` die Priorität und wird von FastAPI bevorzugt verwendet.
So können Sie korrekte Typannotationen zu ihrer Funktion hinzufügen, die von ihrem Editor und Tools wie mypy verwendet werden. Und dennoch übernimmt FastAPI die Validierung und Dokumentation, usw., der Daten anhand von `response_model`.
So können Sie korrekte Typannotationen zu Ihrer Funktion hinzufügen, die von Ihrem Editor und Tools wie mypy verwendet werden. Und dennoch übernimmt FastAPI die Validierung und Dokumentation, usw., der Daten anhand von `response_model`.
Sie können auch `response_model=None` verwenden, um das Erstellen eines Responsemodells für diese *Pfadoperation* zu unterbinden. Sie könnten das tun wollen, wenn sie Dinge annotieren, die nicht gültige Pydantic-Felder sind. Ein Beispiel dazu werden Sie in einer der Abschnitte unten sehen.
Sie können auch `response_model=None` verwenden, um das Erstellen eines Responsemodells für diese *Pfadoperation* zu unterbinden. Sie könnten das tun wollen, wenn Sie Dinge annotieren, die nicht gültige Pydantic-Felder sind. Ein Beispiel dazu werden Sie in einer der Abschnitte unten sehen.
## Dieselben Eingabedaten zurückgeben
## Dieselben Eingabedaten zurückgeben { #return-the-same-input-data }
Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passwort:
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
/// info
/// info | 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]`.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann installieren, zum Beispiel:
```console
$ pip install email-validator
```
oder mit:
```console
$ pip install "pydantic[email]"
```
///
@@ -96,7 +105,7 @@ Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie
///
## Ausgabemodell hinzufügen
## Ausgabemodell hinzufügen { #add-an-output-model }
Wir können stattdessen ein Eingabemodell mit dem Klartext-Passwort, und ein Ausgabemodell ohne das Passwort erstellen:
@@ -112,7 +121,7 @@ Obwohl unsere *Pfadoperation-Funktion* hier denselben `user` von der Eingabe zur
Darum wird **FastAPI** sich darum kümmern, dass alle Daten, die nicht im Ausgabemodell deklariert sind, herausgefiltert werden (mittels Pydantic).
### `response_model` oder Rückgabewert
### `response_model` oder Rückgabewert { #response-model-or-return-type }
Da unsere zwei Modelle in diesem Fall unterschiedlich sind, würde, wenn wir den Rückgabewert der Funktion als `UserOut` deklarieren, der Editor sich beschweren, dass wir einen ungültigen Typ zurückgeben, weil das unterschiedliche Klassen sind.
@@ -120,11 +129,11 @@ Darum müssen wir es in diesem Fall im `response_model`-Parameter deklarieren.
... aber lesen Sie weiter, um zu sehen, wie man das anders lösen kann.
## Rückgabewert und Datenfilterung
## Rückgabewert und Datenfilterung { #return-type-and-data-filtering }
Führen wir unser vorheriges Beispiel fort. Wir wollten **die Funktion mit einem Typ annotieren**, aber etwas zurückgeben, das **weniger Daten** enthält.
Führen wir unser vorheriges Beispiel fort. Wir wollten **die Funktion mit einem Typ annotieren**, aber wir wollten in der Funktion tatsächlich etwas zurückgeben, das **mehr Daten** enthält.
Wir möchten auch, dass FastAPI die Daten weiterhin, dem Responsemodell entsprechend, **filtert**.
Wir möchten, dass FastAPI die Daten weiterhin mithilfe des Responsemodells **filtert**. Selbst wenn die Funktion mehr Daten zurückgibt, soll die Response nur die Felder enthalten, die im Responsemodell deklariert sind.
Im vorherigen Beispiel mussten wir den `response_model`-Parameter verwenden, weil die Klassen unterschiedlich waren. Das bedeutet aber auch, wir bekommen keine Unterstützung vom Editor und anderen Tools, die den Funktions-Rückgabewert überprüfen.
@@ -138,17 +147,17 @@ Damit erhalten wir Tool-Unterstützung, vom Editor und mypy, da dieser Code hins
Wie funktioniert das? Schauen wir uns das mal an. 🤓
### Typannotationen und Tooling
### Typannotationen und Tooling { #type-annotations-and-tooling }
Sehen wir uns zunächst an, wie Editor, mypy und andere Tools dies sehen würden.
`BaseUser` verfügt über die Basis-Felder. Dann erbt `UserIn` von `BaseUser` und fügt das Feld `Passwort` hinzu, sodass dass es nun alle Felder beider Modelle hat.
`BaseUser` verfügt über die Basis-Felder. Dann erbt `UserIn` von `BaseUser` und fügt das Feld `password` hinzu, sodass es nun alle Felder beider Modelle hat.
Wir annotieren den Funktionsrückgabetyp als `BaseUser`, geben aber tatsächlich eine `UserIn`-Instanz zurück.
Für den Editor, mypy und andere Tools ist das kein Problem, da `UserIn` eine Unterklasse von `BaseUser` ist (Salopp: `UserIn` ist ein `BaseUser`). Es handelt sich um einen *gültigen* Typ, solange irgendetwas überreicht wird, das ein `BaseUser` ist.
### FastAPI Datenfilterung
### FastAPI Datenfilterung { #fastapi-data-filtering }
FastAPI seinerseits wird den Rückgabetyp sehen und sicherstellen, dass das, was zurückgegeben wird, **nur** diejenigen Felder enthält, welche im Typ deklariert sind.
@@ -156,7 +165,7 @@ FastAPI macht intern mehrere Dinge mit Pydantic, um sicherzustellen, dass obige
Auf diese Weise erhalten Sie das beste beider Welten: Sowohl Typannotationen mit **Tool-Unterstützung** als auch **Datenfilterung**.
## Anzeige in der Dokumentation
## Anzeige in der Dokumentation { #see-it-in-the-docs }
Wenn Sie sich die automatische Dokumentation betrachten, können Sie sehen, dass Eingabe- und Ausgabemodell beide ihr eigenes JSON-Schema haben:
@@ -166,11 +175,11 @@ Und beide Modelle werden auch in der interaktiven API-Dokumentation verwendet:
<img src="/img/tutorial/response-model/image02.png">
## Andere Rückgabetyp-Annotationen
## Andere Rückgabetyp-Annotationen { #other-return-type-annotations }
Es kann Fälle geben, bei denen Sie etwas zurückgeben, das kein gültiges Pydantic-Feld ist, und Sie annotieren es in der Funktion nur, um Unterstützung von Tools zu erhalten (Editor, mypy, usw.).
### Eine Response direkt zurückgeben
### Eine Response direkt zurückgeben { #return-a-response-directly }
Der häufigste Anwendungsfall ist, wenn Sie [eine Response direkt zurückgeben, wie es später im Handbuch für fortgeschrittene Benutzer erläutert wird](../advanced/response-directly.md){.internal-link target=_blank}.
@@ -180,7 +189,7 @@ Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die
Und Tools werden auch glücklich sein, weil sowohl `RedirectResponse` als auch `JSONResponse` Unterklassen von `Response` sind, die Typannotation ist daher korrekt.
### Eine Unterklasse von Response annotieren
### Eine Unterklasse von Response annotieren { #annotate-a-response-subclass }
Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden.
@@ -188,17 +197,17 @@ Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden.
Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kümmert.
### Ungültige Rückgabetyp-Annotationen
### Ungültige Rückgabetyp-Annotationen { #invalid-return-type-annotations }
Aber wenn Sie ein beliebiges anderes Objekt zurückgeben, das kein gültiger Pydantic-Typ ist (z. B. ein Datenbank-Objekt), und Sie annotieren es so in der Funktion, wird FastAPI versuchen, ein Pydantic-Responsemodell von dieser Typannotation zu erstellen, und scheitern.
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 💥:
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 💥:
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
... 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`.
### Responsemodell deaktivieren
### Responsemodell deaktivieren { #disable-response-model }
Beim Beispiel oben fortsetzend, mögen Sie vielleicht die standardmäßige Datenvalidierung, -Dokumentation, -Filterung, usw., die von FastAPI durchgeführt wird, nicht haben.
@@ -210,7 +219,7 @@ In diesem Fall können Sie die Generierung des Responsemodells abschalten, indem
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. 🤓
## Parameter für die Enkodierung des Responsemodells
## Parameter für die Enkodierung des Responsemodells { #response-model-encoding-parameters }
Ihr Responsemodell könnte Defaultwerte haben, wie:
@@ -224,7 +233,7 @@ Aber Sie möchten diese vielleicht vom Resultat ausschließen, wenn Sie gar nich
Wenn Sie zum Beispiel Modelle mit vielen optionalen Attributen in einer NoSQL-Datenbank haben, und Sie möchten nicht ellenlange JSON-Responses voller Defaultwerte senden.
### Den `response_model_exclude_unset`-Parameter verwenden
### Den `response_model_exclude_unset`-Parameter verwenden { #use-the-response-model-exclude-unset-parameter }
Sie können den *Pfadoperation-Dekorator*-Parameter `response_model_exclude_unset=True` setzen:
@@ -241,21 +250,21 @@ Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wir
}
```
/// info
/// info | Info
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> (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.
///
/// info
/// info | 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.
///
/// info
/// info | Info
Sie können auch:
@@ -266,9 +275,9 @@ verwenden, wie in der <a href="https://docs.pydantic.dev/1.10/usage/exporting_mo
///
#### Daten mit Werten für Felder mit Defaultwerten
#### Daten mit Werten für Felder mit Defaultwerten { #data-with-values-for-fields-with-defaults }
Aber wenn ihre Daten Werte für Modellfelder mit Defaultwerten haben, wie etwa der Artikel mit der ID `bar`:
Aber wenn Ihre Daten Werte für Modellfelder mit Defaultwerten haben, wie etwa der Artikel mit der ID `bar`:
```Python hl_lines="3 5"
{
@@ -281,7 +290,7 @@ Aber wenn ihre Daten Werte für Modellfelder mit Defaultwerten haben, wie etwa d
dann werden diese Werte in der Response enthalten sein.
#### Daten mit den gleichen Werten wie die Defaultwerte
#### Daten mit den gleichen Werten wie die Defaultwerte { #data-with-the-same-values-as-the-defaults }
Wenn Daten die gleichen Werte haben wie ihre Defaultwerte, wie etwa der Artikel mit der ID `baz`:
@@ -307,7 +316,7 @@ Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein.
///
### `response_model_include` und `response_model_exclude`
### `response_model_include` und `response_model_exclude` { #response-model-include-and-response-model-exclude }
Sie können auch die Parameter `response_model_include` und `response_model_exclude` im **Pfadoperation-Dekorator** verwenden.
@@ -319,7 +328,7 @@ Das kann als schnelle Abkürzung verwendet werden, wenn Sie nur ein Pydantic-Mod
Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter.
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.
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.
Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert.
@@ -335,13 +344,13 @@ Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten.
///
#### `list`en statt `set`s verwenden
#### `list`en statt `set`s verwenden { #using-lists-instead-of-sets }
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:
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
## Zusammenfassung
## Zusammenfassung { #recap }
Verwenden Sie den Parameter `response_model` im *Pfadoperation-Dekorator*, um Responsemodelle zu definieren, und besonders, um private Daten herauszufiltern.
+32 -32
View File
@@ -1,6 +1,6 @@
# Response-Statuscode
# Response-Statuscode { #response-status-code }
So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Response deklarieren, mithilfe des Parameters `status_code`, und zwar in jeder der *Pfadoperationen*:
Genauso wie Sie ein Responsemodell angeben können, können Sie auch den HTTP-Statuscode für die <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> mit dem Parameter `status_code` in jeder der *Pfadoperationen* deklarieren:
* `@app.get()`
* `@app.post()`
@@ -12,90 +12,90 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo
/// 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.
Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, wie alle anderen Parameter und der Body.
///
Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben.
/// info
/// info | 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>.
Alternativ kann `status_code` auch ein `IntEnum` erhalten, wie etwa Pythons <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
///
Das wird:
Dies wird:
* Diesen Statuscode mit der Response zurücksenden.
* Ihn als solchen im OpenAPI-Schema dokumentieren (und somit in den Benutzeroberflächen):
* Diesen im OpenAPI-Schema dokumentieren (und somit in den Benutzeroberflächen):
<img src="/img/tutorial/response-status-code/image01.png">
/// note | Hinweis
Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat.
Einige Responsecodes (siehe nächsten Abschnitt) kennzeichnen, dass die Response keinen Body hat.
FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt.
FastAPI erkennt dies und erstellt eine OpenAPI-Dokumentation, die zeigt, dass es keinen Responsebody gibt.
///
## Über HTTP-Statuscodes
## Über HTTP-Statuscodes { #about-http-status-codes }
/// note | Hinweis
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, können Sie diesen Abschnitt überspringen und mit dem nächsten fortfahren.
///
In HTTP senden Sie als Teil der Response einen aus drei Ziffern bestehenden numerischen Statuscode.
In HTTP senden Sie einen numerischen Statuscode mit 3 Ziffern als Teil der Response.
Diese Statuscodes haben einen Namen zugeordnet, um sie besser zu erkennen, aber der wichtige Teil ist die Zahl.
Diese Statuscodes haben einen zugeordneten Namen, um sie leichter zu erkennen, aber der wichtige Teil ist die Zahl.
Kurz:
Kurz gefasst:
* `100` und darüber stehen für „Information“. Diese verwenden Sie selten direkt. Responses mit diesen Statuscodes können keinen Body haben.
* **`200`** und darüber stehen für Responses, die „Successful“ („Erfolgreich“) waren. Diese verwenden Sie am häufigsten.
* `200` ist der Default-Statuscode, welcher bedeutet, alles ist „OK“.
* Ein anderes Beispiel ist `201`, „Created“ („Erzeugt“). Wird in der Regel verwendet, wenn ein neuer Datensatz in der Datenbank erzeugt wurde.
* Ein spezieller Fall ist `204`, „No Content“ („Kein Inhalt“). Diese Response wird verwendet, wenn es keinen Inhalt gibt, der zum Client zurückgeschickt wird, diese Response hat also keinen Body.
* **`300`** und darüber steht für „Redirection“ („Umleitung“). Responses mit diesen Statuscodes können einen oder keinen Body haben, mit Ausnahme von `304`, „Not Modified“ („Nicht verändert“), welche keinen haben darf.
* **`400`** und darüber stehen für „Client error“-Responses („Client-Fehler“). Auch diese verwenden Sie am häufigsten.
* `100 - 199` stehen für „Information“. Sie verwenden diese selten direkt. Responses mit diesen Statuscodes dürfen keinen Body haben.
* **`200 - 299`** stehen für „Successful“-Responses („Erfolgreich“). Diese werden Sie am häufigsten verwenden.
* `200` ist der Default-Statuscode, was bedeutet, alles ist „OK“.
* Ein weiteres Beispiel wäre `201`, „Created“ („Erzeugt“). Dieser wird üblicherweise verwendet, nachdem ein neuer Datensatz in der Datenbank erstellt wurde.
* Ein spezieller Fall ist `204`, „No Content“ („Kein Inhalt“). Diese Response wird verwendet, wenn es keinen Inhalt gibt, der an den Client zurückgeschickt werden soll, und diese Response darf daher keinen Body haben.
* **`300 - 399`** stehen für „Redirection“ („Umleitung“). Responses mit diesen Statuscodes können einen Body haben oder nicht, außer bei `304`, „Not Modified“ („Nicht verändert“), die keinen haben darf.
* **`400 - 499`** stehen für „Client error“-Responses („Client-Fehler“). Diese sind die zweithäufigsten, die Sie vermutlich verwenden werden.
* Ein Beispiel ist `404`, für eine „Not Found“-Response („Nicht gefunden“).
* 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.
* `500 - 599` stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn in Ihrem Anwendungscode oder Server etwas schiefgeht, 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>.
Um mehr über die einzelnen Statuscodes zu erfahren und welcher wofür verwendet wird, sehen Sie sich die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwicklernetzwerk">MDN</abbr> Dokumentation über HTTP-Statuscodes</a> an.
///
## Abkürzung, um die Namen zu erinnern
## Abkürzung zur Erinnerung an die Namen { #shortcut-to-remember-the-names }
Schauen wir uns das vorherige Beispiel noch einmal an:
Lassen Sie uns das vorherige Beispiel noch einmal anschauen:
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
`201` ist der Statuscode für „Created“ („Erzeugt“).
Aber Sie müssen sich nicht daran erinnern, welcher dieser Codes was bedeutet.
Aber Sie müssen sich nicht merken, was jeder dieser Codes bedeutet.
Sie können die Hilfsvariablen von `fastapi.status` verwenden.
Sie können die Annehmlichkeit von Variablen aus `fastapi.status` nutzen.
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese Weise können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:
Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:
<img src="/img/tutorial/response-status-code/image02.png">
/// note | Technische Details
Sie können auch `from starlette import status` verwenden.
Sie könnten 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.
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, rein zu Ihrer Annehmlichkeit als Entwickler. Aber sie stammen direkt von Starlette.
///
## Den Defaultwert ändern
## Den Defaultwert ändern { #changing-the-default }
Später sehen Sie, im [Handbuch für fortgeschrittene Benutzer](../advanced/response-change-status-code.md){.internal-link target=_blank}, wie Sie einen anderen Statuscode zurückgeben können, als den Default, den Sie hier deklarieren.
Später im [Handbuch für fortgeschrittene Benutzer](../advanced/response-change-status-code.md){.internal-link target=_blank} werden Sie sehen, wie Sie einen anderen Statuscode zurückgeben können, als den Default, den Sie hier deklarieren.
+27 -27
View File
@@ -1,10 +1,10 @@
# Beispiel-Request-Daten deklarieren
# Beispiel-Request-Daten deklarieren { #declare-request-example-data }
Sie können Beispiele für die Daten deklarieren, die Ihre Anwendung empfangen kann.
Sie können Beispiele für die Daten deklarieren, die Ihre App empfangen kann.
Hier sind mehrere Möglichkeiten, das zu tun.
## Zusätzliche JSON-Schemadaten in Pydantic-Modellen
## Zusätzliche JSON-Schemadaten in Pydantic-Modellen { #extra-json-schema-data-in-pydantic-models }
Sie können `examples` („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden.
@@ -24,7 +24,7 @@ Diese zusätzlichen Informationen werden unverändert zum für dieses Modell aus
//// 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 <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> 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`.
@@ -46,23 +46,23 @@ Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benut
///
/// info
/// info | 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. 🤓
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="deprecatet – veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</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`
## Zusätzliche Argumente für `Field` { #field-additional-arguments }
Wenn Sie `Field()` mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche `examples` deklarieren:
{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
## `examples` im JSON-Schema – OpenAPI
## `examples` im JSON-Schema – OpenAPI { #examples-in-json-schema-openapi }
Bei Verwendung von:
@@ -76,19 +76,19 @@ Bei Verwendung von:
können Sie auch eine Gruppe von `examples` mit zusätzlichen Informationen deklarieren, die zu ihren **JSON-Schemas** innerhalb von **OpenAPI** hinzugefügt werden.
### `Body` mit `examples`
### `Body` mit `examples` { #body-with-examples }
Hier übergeben wir `examples`, welches ein einzelnes Beispiel für die in `Body()` erwarteten Daten enthält:
{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
### Beispiel in der Dokumentations-Benutzeroberfläche
### Beispiel in der Dokumentations-Benutzeroberfläche { #example-in-the-docs-ui }
Mit jeder der oben genannten Methoden würde es in `/docs` so aussehen:
<img src="/img/tutorial/body-fields/image01.png">
### `Body` mit mehreren `examples`
### `Body` mit mehreren `examples` { #body-with-multiple-examples }
Sie können natürlich auch mehrere `examples` übergeben:
@@ -96,9 +96,9 @@ Sie können natürlich auch mehrere `examples` übergeben:
Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** für diese Body-Daten.
<abbr title="26.08.2023">Während dies geschrieben wird</abbr>, unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, jedoch nicht die Anzeige mehrerer Beispiele für die Daten in **JSON Schema**. Aber lesen Sie unten für einen Workaround weiter.
<abbr title="2023-08-26">Während dies geschrieben wird</abbr>, unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, jedoch nicht die Anzeige mehrerer Beispiele für die Daten in **JSON Schema**. Aber lesen Sie unten für einen Workaround weiter.
### OpenAPI-spezifische `examples`
### OpenAPI-spezifische `examples` { #openapi-specific-examples }
Schon bevor **JSON Schema** `examples` unterstützte, unterstützte OpenAPI ein anderes Feld, das auch `examples` genannt wurde.
@@ -106,11 +106,11 @@ Diese **OpenAPI-spezifischen** `examples` finden sich in einem anderen Abschnitt
Und Swagger UI unterstützt dieses spezielle Feld `examples` schon seit einiger Zeit. Sie können es also verwenden, um verschiedene **Beispiele in der Benutzeroberfläche der Dokumentation anzuzeigen**.
Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **mehreren Beispielen** (anstelle einer `list`e), jedes mit zusätzlichen Informationen, die auch zu **OpenAPI** hinzugefügt werden.
Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **mehreren Beispielen** (anstelle einer `list`), jedes mit zusätzlichen Informationen, die auch zu **OpenAPI** hinzugefügt werden.
Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der *Pfadoperation*.
### Verwendung des Parameters `openapi_examples`
### Verwendung des Parameters `openapi_examples` { #using-the-openapi-examples-parameter }
Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `openapi_examples` deklarieren, für:
@@ -122,7 +122,7 @@ Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `op
* `Form()`
* `File()`
Die Schlüssel des `dict` identifizieren jedes Beispiel, und jeder Wert (`"value"`) ist ein weiteres `dict`.
Die Schlüssel des `dict` identifizieren jedes Beispiel, und jeder Wert ist ein weiteres `dict`.
Jedes spezifische Beispiel-`dict` in den `examples` kann Folgendes enthalten:
@@ -135,13 +135,13 @@ Sie können es so verwenden:
{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche
### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche { #openapi-examples-in-the-docs-ui }
Wenn `openapi_examples` zu `Body()` hinzugefügt wird, würde `/docs` so aussehen:
<img src="/img/tutorial/body-fields/image02.png">
## Technische Details
## Technische Details { #technical-details }
/// tip | Tipp
@@ -177,23 +177,23 @@ OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Sp
* `File()`
* `Form()`
/// info
/// info | Info
Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`.
///
### JSON Schemas Feld `examples`
### JSON Schemas Feld `examples` { #json-schemas-examples-field }
Aber dann fügte JSON Schema ein <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>-Feld zu einer neuen Version der Spezifikation hinzu.
Und dann basierte das neue OpenAPI 3.1.0 auf der neuesten Version (JSON Schema 2020-12), die dieses neue Feld `examples` enthielt.
Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdefinierten) `example`-Feld, im Singular, das jetzt deprecated ist.
Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdefinierten) `example`-Feld, im Singular, das jetzt <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> ist.
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).
Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben).
/// info
/// info | 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 🎉).
@@ -201,7 +201,7 @@ Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Version
///
### Pydantic- und FastAPI-`examples`
### Pydantic- und FastAPI-`examples` { #pydantic-and-fastapi-examples }
Wenn Sie `examples` innerhalb eines Pydantic-Modells hinzufügen, indem Sie `schema_extra` oder `Field(examples=["something"])` verwenden, wird dieses Beispiel dem **JSON-Schema** für dieses Pydantic-Modell hinzugefügt.
@@ -211,14 +211,14 @@ In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere Open
Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten.
### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples`.
### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples }
Da die Swagger-Benutzeroberfläche derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen.
Um dieses Problem zu lösen, hat FastAPI `0.103.0` **Unterstützung** für die Deklaration desselben alten **OpenAPI-spezifischen** `examples`-Felds mit dem neuen Parameter `openapi_examples` hinzugefügt. 🤓
### Zusammenfassung
### Zusammenfassung { #summary }
Ich habe immer gesagt, dass ich Geschichte nicht so sehr mag ... und jetzt schauen Sie mich an, wie ich „Technikgeschichte“-Unterricht gebe. 😅
Kurz gesagt: **Upgraden Sie auf FastAPI 0.99.0 oder höher**, und die Dinge sind viel **einfacher, konsistenter und intuitiver**, und Sie müssen nicht alle diese historischen Details kennen. 😎
Kurz gesagt: **Aktualisieren Sie auf FastAPI 0.99.0 oder höher**, und die Dinge sind viel **einfacher, konsistenter und intuitiver**, und Sie müssen nicht alle diese historischen Details kennen. 😎
+30 -22
View File
@@ -1,8 +1,8 @@
# Sicherheit – Erste Schritte
# Sicherheit – Erste Schritte { #security-first-steps }
Stellen wir uns vor, dass Sie Ihre **Backend**-API auf einer Domain haben.
Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer mobilen Anwendung).
Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer Mobile-Anwendung).
Und Sie möchten eine Möglichkeit haben, dass sich das Frontend mithilfe eines **Benutzernamens** und eines **Passworts** beim Backend authentisieren kann.
@@ -12,25 +12,33 @@ Aber ersparen wir Ihnen die Zeit, die gesamte lange Spezifikation zu lesen, nur
Lassen Sie uns die von **FastAPI** bereitgestellten Tools verwenden, um Sicherheit zu gewährleisten.
## Wie es aussieht
## Wie es aussieht { #how-it-looks }
Lassen Sie uns zunächst einfach den Code verwenden und sehen, wie er funktioniert, und dann kommen wir zurück, um zu verstehen, was passiert.
## `main.py` erstellen
## `main.py` erstellen { #create-main-py }
Kopieren Sie das Beispiel in eine Datei `main.py`:
{* ../../docs_src/security/tutorial001_an_py39.py *}
## Ausführen
## Ausführen { #run-it }
/// info
/// info | 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>.
Das Paket <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> wird automatisch mit **FastAPI** installiert, wenn Sie den Befehl `pip install "fastapi[standard]"` ausführen.
Z. B. `pip install python-multipart`.
Wenn Sie jedoch den Befehl `pip install fastapi` verwenden, ist das Paket `python-multipart` nicht standardmäßig enthalten.
Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
Um es manuell zu installieren, stellen Sie sicher, dass Sie eine [Virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann mit:
```console
$ pip install python-multipart
```
installieren.
Das liegt daran, dass **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
///
@@ -39,14 +47,14 @@ Führen Sie das Beispiel aus mit:
<div class="termy">
```console
$ uvicorn main:app --reload
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
## Überprüfen
## Es testen { #check-it }
Gehen Sie zu der interaktiven Dokumentation unter: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@@ -80,7 +88,7 @@ Es kann von Anwendungen und Systemen Dritter verwendet werden.
Und es kann auch von Ihnen selbst verwendet werden, um dieselbe Anwendung zu debuggen, zu prüfen und zu testen.
## Der `password`-Flow
## Der `password`-Flow { #the-password-flow }
Lassen Sie uns nun etwas zurückgehen und verstehen, was das alles ist.
@@ -103,16 +111,16 @@ Betrachten wir es also aus dieser vereinfachten Sicht:
* Der Benutzer klickt im Frontend, um zu einem anderen Abschnitt der Frontend-Web-Anwendung zu gelangen.
* Das Frontend muss weitere Daten von der API abrufen.
* Es benötigt jedoch eine Authentifizierung für diesen bestimmten Endpunkt.
* Um sich also bei unserer API zu authentifizieren, sendet es einen Header `Authorization` mit dem Wert `Bearer` plus dem Token.
* Um sich also bei unserer API zu authentifizieren, sendet es einen Header `Authorization` mit dem Wert `Bearer ` plus dem Token.
* Wenn der Token `foobar` enthielte, wäre der Inhalt des `Authorization`-Headers: `Bearer foobar`.
## **FastAPI**s `OAuth2PasswordBearer`
## **FastAPI**s `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer }
**FastAPI** bietet mehrere Tools auf unterschiedlichen Abstraktionsebenen zur Implementierung dieser Sicherheitsfunktionen.
In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`.
/// info
/// info | Info
Ein „Bearer“-Token ist nicht die einzige Option.
@@ -142,7 +150,7 @@ Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern
Wir werden demnächst auch die eigentliche Pfadoperation erstellen.
/// info
/// info | Info
Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`.
@@ -160,7 +168,7 @@ oauth2_scheme(some, parameters)
Es kann also mit `Depends` verwendet werden.
### Verwendung
### Verwenden { #use-it }
Jetzt können Sie dieses `oauth2_scheme` als Abhängigkeit `Depends` übergeben.
@@ -178,11 +186,11 @@ Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische
///
## Was es macht
## Was es macht { #what-it-does }
FastAPI wird im Request nach diesem `Authorization`-Header suchen, prüfen, ob der Wert `Bearer` plus ein Token ist, und den Token als `str` zurückgeben.
FastAPI wird im <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> nach diesem `Authorization`-Header suchen, prüfen, ob der Wert `Bearer ` plus ein Token ist, und den Token als `str` zurückgeben.
Wenn es keinen `Authorization`-Header sieht, oder der Wert keinen `Bearer`-Token hat, antwortet es direkt mit einem 401-Statuscode-Error (`UNAUTHORIZED`).
Wenn es keinen `Authorization`-Header sieht, oder der Wert keinen `Bearer `-Token hat, antwortet es direkt mit einem 401-Statuscode-Error (`UNAUTHORIZED`).
Sie müssen nicht einmal prüfen, ob der Token existiert, um einen Fehler zurückzugeben. Seien Sie sicher, dass Ihre Funktion, wenn sie ausgeführt wird, ein `str` in diesem Token enthält.
@@ -192,6 +200,6 @@ Sie können das bereits in der interaktiven Dokumentation ausprobieren:
Wir überprüfen im Moment noch nicht die Gültigkeit des Tokens, aber das ist bereits ein Anfang.
## Zusammenfassung
## Zusammenfassung { #recap }
Mit nur drei oder vier zusätzlichen Zeilen haben Sie also bereits eine primitive Form der Sicherheit.
Mit nur drei oder vier zusätzlichen Zeilen haben Sie so bereits eine primitive Form der Sicherheit.
@@ -1,4 +1,4 @@
# Aktuellen Benutzer abrufen
# Aktuellen Benutzer abrufen { #get-current-user }
Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` überreicht:
@@ -8,15 +8,15 @@ Aber das ist immer noch nicht so nützlich.
Lassen wir es uns den aktuellen Benutzer überreichen.
## Ein Benutzermodell erstellen
## Ein Benutzermodell erstellen { #create-a-user-model }
Erstellen wir zunächst ein Pydantic-Benutzermodell.
So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden:
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *}
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
## Eine `get_current_user`-Abhängigkeit erstellen
## Eine `get_current_user`-Abhängigkeit erstellen { #create-a-get-current-user-dependency }
Erstellen wir eine Abhängigkeit `get_current_user`.
@@ -28,13 +28,13 @@ So wie wir es zuvor in der *Pfadoperation* direkt gemacht haben, erhält unsere
{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *}
## Den Benutzer holen
## Den Benutzer abrufen { #get-the-user }
`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:
{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
## Den aktuellen Benutzer einfügen
## Den aktuellen Benutzer einfügen { #inject-the-current-user }
Und jetzt können wir wiederum `Depends` mit unserem `get_current_user` in der *Pfadoperation* verwenden:
@@ -46,13 +46,13 @@ Das wird uns innerhalb der Funktion bei Codevervollständigung und Typprüfungen
/// tip | Tipp
Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden.
Sie erinnern sich vielleicht, dass <abbr title="Anfragekörper">Requestbodys</abbr> ebenfalls mit Pydantic-Modellen deklariert werden.
Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt.
///
/// check
/// check | Testen
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.
@@ -60,7 +60,7 @@ Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen T
///
## Andere Modelle
## Andere Modelle { #other-models }
Sie können jetzt den aktuellen Benutzer direkt in den *Pfadoperation-Funktionen* abrufen und die Sicherheitsmechanismen auf **Dependency Injection** Ebene handhaben, mittels `Depends`.
@@ -76,7 +76,7 @@ Sie haben eigentlich keine Benutzer, die sich bei Ihrer Anwendung anmelden, sond
Verwenden Sie einfach jede Art von Modell, jede Art von Klasse, jede Art von Datenbank, die Sie für Ihre Anwendung benötigen. **FastAPI** deckt das alles mit seinem Dependency Injection System ab.
## Codegröße
## Codegröße { #code-size }
Dieses Beispiel mag ausführlich erscheinen. Bedenken Sie, dass wir Sicherheit, Datenmodelle, Hilfsfunktionen und *Pfadoperationen* in derselben Datei vermischen.
@@ -94,7 +94,7 @@ Und alle diese Tausenden von *Pfadoperationen* können nur drei Zeilen lang sein
{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *}
## Zusammenfassung
## Zusammenfassung { #recap }
Sie können jetzt den aktuellen Benutzer direkt in Ihrer *Pfadoperation-Funktion* abrufen.
+9 -9
View File
@@ -1,4 +1,4 @@
# Sicherheit
# Sicherheit { #security }
Es gibt viele Wege, Sicherheit, Authentifizierung und Autorisierung zu handhaben.
@@ -10,11 +10,11 @@ In vielen Frameworks und Systemen erfordert allein die Handhabung von Sicherheit
Aber schauen wir uns zunächst ein paar kleine Konzepte an.
## In Eile?
## In Eile? { #in-a-hurry }
Wenn Ihnen diese Begriffe egal sind und Sie einfach *jetzt* Sicherheit mit Authentifizierung basierend auf Benutzername und Passwort hinzufügen müssen, fahren Sie mit den nächsten Kapiteln fort.
## OAuth2
## OAuth2 { #oauth2 }
OAuth2 ist eine Spezifikation, die verschiedene Möglichkeiten zur Handhabung von Authentifizierung und Autorisierung definiert.
@@ -24,7 +24,7 @@ Sie umfasst Möglichkeiten zur Authentifizierung mithilfe eines „Dritten“ (
Das ist es, was alle diese „Login mit Facebook, Google, X (Twitter), GitHub“-Systeme unter der Haube verwenden.
### OAuth 1
### OAuth 1 { #oauth-1 }
Es gab ein OAuth 1, das sich stark von OAuth2 unterscheidet und komplexer ist, da es direkte Spezifikationen enthält, wie die Kommunikation verschlüsselt wird.
@@ -38,7 +38,7 @@ Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traef
///
## OpenID Connect
## OpenID Connect { #openid-connect }
OpenID Connect ist eine weitere Spezifikation, die auf **OAuth2** basiert.
@@ -48,7 +48,7 @@ Beispielsweise verwendet der Google Login OpenID Connect (welches seinerseits OA
Aber der Facebook Login unterstützt OpenID Connect nicht. Es hat seine eigene Variante von OAuth2.
### OpenID (nicht „OpenID Connect“)
### OpenID (nicht „OpenID Connect“) { #openid-not-openid-connect }
Es gab auch eine „OpenID“-Spezifikation. Sie versuchte das Gleiche zu lösen wie **OpenID Connect**, basierte aber nicht auf OAuth2.
@@ -56,7 +56,7 @@ Es handelte sich also um ein komplett zusätzliches System.
Heutzutage ist es nicht sehr populär und wird kaum verwendet.
## OpenAPI
## OpenAPI { #openapi }
OpenAPI (früher bekannt als Swagger) ist die offene Spezifikation zum Erstellen von APIs (jetzt Teil der Linux Foundation).
@@ -75,7 +75,7 @@ OpenAPI definiert die folgenden Sicherheitsschemas:
* Einem Header.
* Einem Cookie.
* `http`: Standard-HTTP-Authentifizierungssysteme, einschließlich:
* `bearer`: ein Header `Authorization` mit dem Wert `Bearer` plus einem Token. Dies wird von OAuth2 geerbt.
* `bearer`: ein Header `Authorization` mit dem Wert `Bearer ` plus einem Token. Dies wird von OAuth2 geerbt.
* HTTP Basic Authentication.
* HTTP Digest, usw.
* `oauth2`: Alle OAuth2-Methoden zum Umgang mit Sicherheit (genannt „Flows“).
@@ -97,7 +97,7 @@ Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsa
///
## **FastAPI** Tools
## **FastAPI** Tools { #fastapi-utilities }
FastAPI stellt für jedes dieser Sicherheitsschemas im Modul `fastapi.security` verschiedene Tools bereit, die die Verwendung dieser Sicherheitsmechanismen vereinfachen.
+34 -36
View File
@@ -1,4 +1,4 @@
# OAuth2 mit Password (und Hashing), Bearer mit JWT-Tokens
# OAuth2 mit Passwort (und Hashing), Bearer mit JWT-Tokens { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
Da wir nun über den gesamten Sicherheitsablauf verfügen, machen wir die Anwendung tatsächlich sicher, indem wir <abbr title="JSON Web Tokens">JWT</abbr>-Tokens und sicheres Passwort-Hashing verwenden.
@@ -6,7 +6,7 @@ Diesen Code können Sie tatsächlich in Ihrer Anwendung verwenden, die Passwort-
Wir bauen auf dem vorherigen Kapitel auf.
## Über JWT
## Über JWT { #about-jwt }
JWT bedeutet „JSON Web Tokens“.
@@ -26,33 +26,31 @@ Nach einer Woche läuft der Token ab und der Benutzer wird nicht autorisiert und
Wenn Sie mit JWT-Tokens spielen und sehen möchten, wie sie funktionieren, schauen Sie sich <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a> an.
## `python-jose` installieren.
## `PyJWT` installieren { #install-pyjwt }
Wir müssen <abbr title="JOSE: JavaScript Object Signing and Encryption">`python-jose`</abbr> installieren, um die JWT-Tokens in Python zu generieren und zu verifizieren:
Wir müssen `PyJWT` installieren, um die JWT-Tokens in Python zu generieren und zu verifizieren.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann `pyjwt` installieren:
<div class="termy">
```console
$ pip install "python-jose[cryptography]"
$ pip install pyjwt
---> 100%
```
</div>
<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">python-jose</a> erfordert zusätzlich ein kryptografisches Backend.
/// info | Info
Hier verwenden wir das empfohlene: <a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>.
Wenn Sie planen, digitale Signaturalgorithmen wie RSA oder ECDSA zu verwenden, sollten Sie die Kryptografie-Abhängigkeit `pyjwt[crypto]` installieren.
/// tip | Tipp
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.
Weitere Informationen finden Sie in der <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT-Installationsdokumentation</a>.
///
## Passwort-Hashing
## Passwort-Hashing { #password-hashing }
„Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht.
@@ -60,13 +58,13 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben
Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren.
### Warum Passwort-Hashing verwenden?
### Warum Passwort-Hashing verwenden { #why-use-password-hashing }
Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes.
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).
## `passlib` installieren
## `passlib` installieren { #install-passlib }
PassLib ist ein großartiges Python-Package, um Passwort-Hashes zu handhaben.
@@ -74,7 +72,7 @@ Es unterstützt viele sichere Hashing-Algorithmen und Werkzeuge, um mit diesen z
Der empfohlene Algorithmus ist „Bcrypt“.
Installieren Sie also PassLib mit Bcrypt:
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren, und installieren Sie dann PassLib mit Bcrypt:
<div class="termy">
@@ -96,7 +94,7 @@ Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ih
///
## Die Passwörter hashen und überprüfen
## Die Passwörter hashen und überprüfen { #hash-and-verify-the-passwords }
Importieren Sie die benötigten Tools aus `passlib`.
@@ -104,7 +102,7 @@ Erstellen Sie einen PassLib-„Kontext“. Der wird für das Hashen und Verifizi
/// tip | Tipp
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecateter</abbr> Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
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.
@@ -118,7 +116,7 @@ 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.
{* ../../docs_src/security/tutorial004_an_py310.py hl[7,48,55:56,59:60,69:75] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
/// note | Hinweis
@@ -126,7 +124,7 @@ Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie,
///
## JWT-Token verarbeiten
## JWT-Token verarbeiten { #handle-jwt-tokens }
Importieren Sie die installierten Module.
@@ -150,13 +148,13 @@ Erstellen Sie eine Variable `ALGORITHM` für den Algorithmus, der zum Signieren
Erstellen Sie eine Variable für das Ablaufdatum des Tokens.
Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verwendet wird.
Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> verwendet wird.
Erstellen Sie eine Hilfsfunktion, um einen neuen Zugriffstoken zu generieren.
{* ../../docs_src/security/tutorial004_an_py310.py hl[6,12:14,28:30,78:86] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
## Die Abhängigkeiten aktualisieren
## Die Abhängigkeiten aktualisieren { #update-the-dependencies }
Aktualisieren Sie `get_current_user`, um den gleichen Token wie zuvor zu erhalten, dieses Mal jedoch unter Verwendung von JWT-Tokens.
@@ -164,17 +162,17 @@ 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.
{* ../../docs_src/security/tutorial004_an_py310.py hl[89:106] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
## Die *Pfadoperation* `/token` aktualisieren
## Die *Pfadoperation* `/token` aktualisieren { #update-the-token-path-operation }
Erstellen Sie ein <abbr title="Zeitdifferenz">`timedelta`</abbr> mit der Ablaufzeit des Tokens.
Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurück.
{* ../../docs_src/security/tutorial004_an_py310.py hl[117:132] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
### Technische Details zum JWT-„Subjekt“ `sub`
### Technische Details zum JWT-„Subjekt“ `sub` { #technical-details-about-the-jwt-subject-sub }
Die JWT-Spezifikation besagt, dass es einen Schlüssel `sub` mit dem Subjekt des Tokens gibt.
@@ -196,7 +194,7 @@ Deshalb, um ID-Kollisionen zu vermeiden, könnten Sie beim Erstellen des JWT-Tok
Der wesentliche Punkt ist, dass der `sub`-Schlüssel in der gesamten Anwendung eine eindeutige Kennung haben sollte, und er sollte ein String sein.
## Es testen
## Es testen { #check-it }
Führen Sie den Server aus und gehen Sie zur Dokumentation: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@@ -209,11 +207,11 @@ Melden Sie sich bei der Anwendung auf die gleiche Weise wie zuvor an.
Verwenden Sie die Anmeldeinformationen:
Benutzername: `johndoe`
Passwort: `secret`.
Passwort: `secret`
/// check
/// check | Testen
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version.
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort „`secret`“ steht, wir haben nur die gehashte Version.
///
@@ -232,17 +230,17 @@ Rufen Sie den Endpunkt `/users/me/` auf, Sie erhalten die Response:
<img src="/img/tutorial/security/image09.png">
Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Daten nur den Token enthalten. Das Passwort wird nur bei der ersten Anfrage gesendet, um den Benutzer zu authentisieren und diesen Zugriffstoken zu erhalten, aber nicht mehr danach:
Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Daten nur den Token enthalten. Das Passwort wird nur beim ersten <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> gesendet, um den Benutzer zu authentisieren und diesen Zugriffstoken zu erhalten, aber nicht mehr danach:
<img src="/img/tutorial/security/image10.png">
/// note | Hinweis
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt.
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer ` beginnt.
///
## Fortgeschrittene Verwendung mit `scopes`
## Fortgeschrittene Verwendung mit `scopes` { #advanced-usage-with-scopes }
OAuth2 hat ein Konzept von <abbr title="Geltungsbereiche">„Scopes“</abbr>.
@@ -252,7 +250,7 @@ Anschließend können Sie diesen Token einem Benutzer direkt oder einem Dritten
Wie Sie sie verwenden und wie sie in **FastAPI** integriert sind, erfahren Sie später im **Handbuch für fortgeschrittene Benutzer**.
## Zusammenfassung
## Zusammenfassung { #recap }
Mit dem, was Sie bis hier gesehen haben, können Sie eine sichere **FastAPI**-Anwendung mithilfe von Standards wie OAuth2 und JWT einrichten.
@@ -266,7 +264,7 @@ Viele Packages, die es stark vereinfachen, müssen viele Kompromisse beim Datenm
Es gibt Ihnen die volle Flexibilität, diejenigen auszuwählen, die am besten zu Ihrem Projekt passen.
Und Sie können viele gut gepflegte und weit verbreitete Packages wie `passlib` und `python-jose` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert.
Und Sie können viele gut gepflegte und weit verbreitete Packages wie `passlib` und `PyJWT` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert.
Aber es bietet Ihnen die Werkzeuge, um den Prozess so weit wie möglich zu vereinfachen, ohne Kompromisse bei Flexibilität, Robustheit oder Sicherheit einzugehen.
+24 -24
View File
@@ -1,8 +1,8 @@
# Einfaches OAuth2 mit Password und Bearer
# Einfaches OAuth2 mit Password und Bearer { #simple-oauth2-with-password-and-bearer }
Lassen Sie uns nun auf dem vorherigen Kapitel aufbauen und die fehlenden Teile hinzufügen, um einen vollständigen Sicherheits-Flow zu erhalten.
## `username` und `password` entgegennehmen
## `username` und `password` entgegennehmen { #get-the-username-and-password }
Wir werden **FastAPIs** Sicherheits-Werkzeuge verwenden, um den `username` und das `password` entgegenzunehmen.
@@ -18,7 +18,7 @@ Aber für die Login-*Pfadoperation* müssen wir diese Namen verwenden, um mit de
Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten gesendet werden müssen (hier also kein JSON).
### <abbr title="Geltungsbereich">`scope`</abbr>
### <abbr title="Geltungsbereich">`scope`</abbr> { #scope }
Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" („Geltungsbereich“) senden kann.
@@ -32,7 +32,7 @@ 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
/// info | Info
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
@@ -44,11 +44,11 @@ Für OAuth2 sind es einfach nur Strings.
///
## Code, um `username` und `password` entgegenzunehmen.
## Code, um `username` und `password` entgegenzunehmen { #code-to-get-the-username-and-password }
Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um das zu erledigen.
### `OAuth2PasswordRequestForm`
### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform }
Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als Abhängigkeit mit `Depends` in der *Pfadoperation* für `/token`:
@@ -59,7 +59,7 @@ Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als A
* Dem `username`.
* Dem `password`.
* Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings.
* Einem optionalen `grant_type` („Art der Anmeldung“).
* Einem optionalen <abbr title="Art der Anmeldung">`grant_type`</abbr>.
/// tip | Tipp
@@ -72,7 +72,7 @@ Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` a
* 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
/// info | Info
`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`.
@@ -84,7 +84,7 @@ Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinf
///
### Die Formulardaten verwenden
### Die Formulardaten verwenden { #use-the-form-data }
/// tip | Tipp
@@ -102,7 +102,7 @@ Für den Fehler verwenden wir die Exception `HTTPException`:
{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *}
### Das Passwort überprüfen
### Das Passwort überprüfen { #check-the-password }
Zu diesem Zeitpunkt liegen uns die Benutzerdaten aus unserer Datenbank vor, das Passwort haben wir jedoch noch nicht überprüft.
@@ -112,7 +112,7 @@ Sie sollten niemals Klartext-Passwörter speichern, daher verwenden wir ein (gef
Wenn die Passwörter nicht übereinstimmen, geben wir denselben Fehler zurück.
#### Passwort-Hashing
#### Passwort-Hashing { #password-hashing }
„Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht.
@@ -120,7 +120,7 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben
Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren.
##### Warum Passwort-Hashing verwenden?
##### Warum Passwort-Hashing verwenden? { #why-use-password-hashing }
Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes.
@@ -128,7 +128,7 @@ Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen Sy
{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *}
#### Über `**user_dict`
#### Über `**user_dict` { #about-user-dict }
`UserInDB(**user_dict)` bedeutet:
@@ -144,15 +144,15 @@ UserInDB(
)
```
/// info
/// info | 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}.
Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}.
///
## Den Token zurückgeben
## Den Token zurückgeben { #return-the-token }
Die Response des `token`-Endpunkts muss ein JSON-Objekt sein.
Die <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> des `token`-Endpunkts muss ein JSON-Objekt sein.
Es sollte einen `token_type` haben. Da wir in unserem Fall „Bearer“-Token verwenden, sollte der Token-Typ "`bearer`" sein.
@@ -182,7 +182,7 @@ Den Rest erledigt **FastAPI** für Sie.
///
## Die Abhängigkeiten aktualisieren
## Die Abhängigkeiten aktualisieren { #update-the-dependencies }
Jetzt werden wir unsere Abhängigkeiten aktualisieren.
@@ -196,7 +196,7 @@ In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer
{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *}
/// info
/// info | Info
Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation.
@@ -214,11 +214,11 @@ Das ist der Vorteil von Standards ...
///
## Es in Aktion sehen
## Es in Aktion sehen { #see-it-in-action }
Öffnen Sie die interaktive Dokumentation: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
### Authentifizieren
### Authentifizieren { #authenticate }
Klicken Sie auf den Button „Authorize“.
@@ -234,7 +234,7 @@ Nach der Authentifizierung im System sehen Sie Folgendes:
<img src="/img/tutorial/security/image05.png">
### Die eigenen Benutzerdaten ansehen
### Die eigenen Benutzerdaten ansehen { #get-your-own-user-data }
Verwenden Sie nun die Operation `GET` mit dem Pfad `/users/me`.
@@ -260,7 +260,7 @@ Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen V
}
```
### Inaktiver Benutzer
### Inaktiver Benutzer { #inactive-user }
Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit:
@@ -278,7 +278,7 @@ Sie erhalten die Fehlermeldung „Inactive user“:
}
```
## Zusammenfassung
## Zusammenfassung { #recap }
Sie verfügen jetzt über die Tools, um ein vollständiges Sicherheitssystem basierend auf `username` und `password` für Ihre API zu implementieren.
+357
View File
@@ -0,0 +1,357 @@
# SQL (Relationale) Datenbanken { #sql-relational-databases }
**FastAPI** erfordert nicht, dass Sie eine SQL (relationale) Datenbank verwenden. Sondern Sie können **jede beliebige Datenbank** verwenden, die Sie möchten.
Hier werden wir ein Beispiel mit <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel</a> sehen.
**SQLModel** basiert auf <a href="https://www.sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a> und Pydantic. Es wurde vom selben Autor wie **FastAPI** entwickelt, um die perfekte Ergänzung für FastAPI-Anwendungen zu sein, die **SQL-Datenbanken** verwenden müssen.
/// tip | Tipp
Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als <abbr title="Object Relational Mapper – Objektrelationaler Mapper: Ein Fachbegriff für eine Bibliothek, in der einige Klassen SQL-Tabellen und Instanzen Zeilen in diesen Tabellen darstellen">„ORMs“</abbr> bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎
///
Da SQLModel auf SQLAlchemy basiert, können Sie problemlos **jede von SQLAlchemy unterstützte Datenbank** verwenden (was auch bedeutet, dass sie von SQLModel unterstützt werden), wie:
* PostgreSQL
* MySQL
* SQLite
* Oracle
* Microsoft SQL Server, usw.
In diesem Beispiel verwenden wir **SQLite**, da es eine einzelne Datei verwendet und Python integrierte Unterstützung bietet. Sie können also dieses Beispiel kopieren und direkt ausführen.
Später, für Ihre Produktionsanwendung, möchten Sie möglicherweise einen Datenbankserver wie **PostgreSQL** verwenden.
/// tip | Tipp
Es gibt einen offiziellen Projektgenerator mit **FastAPI** und **PostgreSQL**, einschließlich eines Frontends und weiterer Tools: <a href="https://github.com/fastapi/full-stack-fastapi-template" class="external-link" target="_blank">https://github.com/fastapi/full-stack-fastapi-template</a>
///
Dies ist ein sehr einfaches und kurzes Tutorial. Wenn Sie mehr über Datenbanken im Allgemeinen, über SQL oder fortgeschrittenere Funktionen erfahren möchten, besuchen Sie die <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel-Dokumentation</a>.
## `SQLModel` installieren { #install-sqlmodel }
Stellen Sie zunächst sicher, dass Sie Ihre [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann `sqlmodel` installieren:
<div class="termy">
```console
$ pip install sqlmodel
---> 100%
```
</div>
## Die App mit einem einzelnen Modell erstellen { #create-the-app-with-a-single-model }
Wir erstellen zuerst die einfachste erste Version der App mit einem einzigen **SQLModel**-Modell.
Später werden wir sie verbessern, indem wir unter der Haube **mehrere Modelle** verwenden, um Sicherheit und Vielseitigkeit zu erhöhen. 🤓
### Modelle erstellen { #create-models }
Importieren Sie `SQLModel` und erstellen Sie ein Datenbankmodell:
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *}
Die `Hero`-Klasse ist einem Pydantic-Modell sehr ähnlich (faktisch ist sie darunter tatsächlich *ein Pydantic-Modell*).
Es gibt ein paar Unterschiede:
* `table=True` sagt SQLModel, dass dies ein *Tabellenmodell* ist, es soll eine **Tabelle** in der SQL-Datenbank darstellen, es ist nicht nur ein *Datenmodell* (wie es jede andere reguläre Pydantic-Klasse wäre).
* `Field(primary_key=True)` sagt SQLModel, dass die `id` der **Primärschlüssel** in der SQL-Datenbank ist (Sie können mehr über SQL-Primärschlüssel in der SQLModel-Dokumentation erfahren).
Durch das Festlegen des Typs als `int | None` wird SQLModel wissen, dass diese Spalte ein `INTEGER` in der SQL-Datenbank sein sollte und dass sie `NULLABLE` sein sollte.
* `Field(index=True)` sagt SQLModel, dass es einen **SQL-Index** für diese Spalte erstellen soll, was schnelleres Suchen in der Datenbank ermöglicht, wenn Daten mittels dieser Spalte gefiltert werden.
SQLModel wird verstehen, dass etwas, das als `str` deklariert ist, eine SQL-Spalte des Typs `TEXT` (oder `VARCHAR`, abhängig von der Datenbank) sein wird.
### Eine Engine erstellen { #create-an-engine }
Eine SQLModel-`engine` (darunter ist es tatsächlich eine SQLAlchemy-`engine`) ist das, was die **Verbindungen** zur Datenbank hält.
Sie hätten **ein einziges `engine`-Objekt** für Ihren gesamten Code, um sich mit derselben Datenbank zu verbinden.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *}
Die Verwendung von `check_same_thread=False` erlaubt FastAPI, dieselbe SQLite-Datenbank in verschiedenen Threads zu verwenden. Dies ist notwendig, da **ein einzelner <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr>** **mehr als einen Thread** verwenden könnte (zum Beispiel in Abhängigkeiten).
Keine Sorge, so wie der Code strukturiert ist, werden wir später sicherstellen, dass wir **eine einzige SQLModel-*Session* pro Request** verwenden, das ist eigentlich das, was `check_same_thread` erreichen möchte.
### Die Tabellen erstellen { #create-the-tables }
Dann fügen wir eine Funktion hinzu, die `SQLModel.metadata.create_all(engine)` verwendet, um die **Tabellen für alle *Tabellenmodelle* zu erstellen**.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
### Eine Session-Abhängigkeit erstellen { #create-a-session-dependency }
Eine <abbr title="Sitzung">**`Session`**</abbr> speichert die **Objekte im Speicher** und verfolgt alle Änderungen, die an den Daten vorgenommen werden müssen, dann **verwendet sie die `engine`**, um mit der Datenbank zu kommunizieren.
Wir werden eine FastAPI **Abhängigkeit** mit `yield` erstellen, die eine neue `Session` für jeden Request bereitstellt. Das ist es, was sicherstellt, dass wir eine einzige Session pro Request verwenden. 🤓
Dann erstellen wir eine `Annotated`-Abhängigkeit `SessionDep`, um den Rest des Codes zu vereinfachen, der diese Abhängigkeit nutzen wird.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *}
### Die Datenbanktabellen beim Start erstellen { #create-database-tables-on-startup }
Wir werden die Datenbanktabellen erstellen, wenn die Anwendung startet.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *}
Hier erstellen wir die Tabellen bei einem Anwendungsstart-Event.
Für die Produktion würden Sie wahrscheinlich ein Migrationsskript verwenden, das ausgeführt wird, bevor Sie Ihre App starten. 🤓
/// tip | Tipp
SQLModel wird Migrationstools haben, die Alembic wrappen, aber im Moment können Sie <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a> direkt verwenden.
///
### Einen Helden erstellen { #create-a-hero }
Da jedes SQLModel-Modell auch ein Pydantic-Modell ist, können Sie es in denselben **Typannotationen** verwenden, die Sie für Pydantic-Modelle verwenden könnten.
Wenn Sie beispielsweise einen Parameter vom Typ `Hero` deklarieren, wird er aus dem **JSON-Body** gelesen.
Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentation angezeigt.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *}
Hier verwenden wir die `SessionDep`-Abhängigkeit (eine `Session`), um den neuen `Hero` zur `Session`-Instanz hinzuzufügen, die Änderungen an der Datenbank zu committen, die Daten im `hero` zu aktualisieren und ihn anschließend zurückzugeben.
### Helden lesen { #read-heroes }
Wir können `Hero`s aus der Datenbank mit einem `select()` **lesen**. Wir können ein `limit` und `offset` hinzufügen, um die Ergebnisse zu paginieren.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
### Einen Helden lesen { #read-one-hero }
Wir können einen einzelnen `Hero` **lesen**.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
### Einen Helden löschen { #delete-a-hero }
Wir können auch einen `Hero` **löschen**.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
### Die App ausführen { #run-the-app }
Sie können die App ausführen:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Gehen Sie dann zur `/docs`-UI, Sie werden sehen, dass **FastAPI** diese **Modelle** verwendet, um die API zu **dokumentieren**, und es wird sie auch verwenden, um die Daten zu **serialisieren** und zu **validieren**.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image01.png">
</div>
## Die App mit mehreren Modellen aktualisieren { #update-the-app-with-multiple-models }
Jetzt lassen Sie uns diese App ein wenig **refaktorisieren**, um die **Sicherheit** und **Vielseitigkeit** zu erhöhen.
Wenn Sie die vorherige App überprüfen, können Sie in der UI sehen, dass sie bis jetzt dem Client erlaubt, die `id` des zu erstellenden `Hero` zu bestimmen. 😱
Das sollten wir nicht zulassen, sie könnten eine `id` überschreiben, die wir bereits in der DB zugewiesen haben. Die Entscheidung über die `id` sollte vom **Backend** oder der **Datenbank** getroffen werden, **nicht vom Client**.
Außerdem erstellen wir einen `secret_name` für den Helden, aber bisher geben wir ihn überall zurück, das ist nicht sehr **geheim** ... 😅
Wir werden diese Dinge beheben, indem wir ein paar **zusätzliche Modelle** hinzufügen. Hier wird SQLModel glänzen. ✨
### Mehrere Modelle erstellen { #create-multiple-models }
In **SQLModel** ist jede Modellklasse, die `table=True` hat, ein **Tabellenmodell**.
Und jede Modellklasse, die `table=True` nicht hat, ist ein **Datenmodell**, diese sind tatsächlich nur Pydantic-Modelle (mit ein paar kleinen zusätzlichen Funktionen). 🤓
Mit SQLModel können wir **Vererbung** verwenden, um **doppelte Felder** in allen Fällen zu **vermeiden**.
#### `HeroBase` – die Basisklasse { #herobase-the-base-class }
Fangen wir mit einem `HeroBase`-Modell an, das alle **Felder hat, die von allen Modellen geteilt werden**:
* `name`
* `age`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
#### `Hero` – das *Tabellenmodell* { #hero-the-table-model }
Dann erstellen wir `Hero`, das tatsächliche *Tabellenmodell*, mit den **zusätzlichen Feldern**, die nicht immer in den anderen Modellen enthalten sind:
* `id`
* `secret_name`
Da `Hero` von `HeroBase` erbt, hat es **auch** die **Felder**, die in `HeroBase` deklariert sind, also sind alle Felder von `Hero`:
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
#### `HeroPublic` – das öffentliche *Datenmodell* { #heropublic-the-public-data-model }
Als nächstes erstellen wir ein `HeroPublic`-Modell, das an die API-Clients **zurückgegeben** wird.
Es hat dieselben Felder wie `HeroBase`, sodass es `secret_name` nicht enthält.
Endlich ist die Identität unserer Helden geschützt! 🥷
Es deklariert auch `id: int` erneut. Indem wir dies tun, machen wir einen **Vertrag** mit den API-Clients, damit sie immer damit rechnen können, dass die `id` vorhanden ist und ein `int` ist (sie wird niemals `None` sein).
/// tip | Tipp
Es ist sehr nützlich für die API-Clients, wenn das Rückgabemodell sicherstellt, dass ein Wert immer verfügbar und immer `int` (nicht `None`) ist, sie können viel einfacheren Code schreiben, wenn sie diese Sicherheit haben.
Auch **automatisch generierte Clients** werden einfachere Schnittstellen haben, damit die Entwickler, die mit Ihrer API kommunizieren, viel mehr Freude an der Arbeit mit Ihrer API haben können. 😎
///
Alle Felder in `HeroPublic` sind dieselben wie in `HeroBase`, mit `id`, das als `int` (nicht `None`) deklariert ist:
* `id`
* `name`
* `age`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
#### `HeroCreate` – das *Datenmodell* zum Erstellen eines Helden { #herocreate-the-data-model-to-create-a-hero }
Nun erstellen wir ein `HeroCreate`-Modell, das die Daten der Clients **validiert**.
Es hat dieselben Felder wie `HeroBase`, und es hat auch `secret_name`.
Wenn die Clients **einen neuen Helden erstellen**, senden sie jetzt den `secret_name`, er wird in der Datenbank gespeichert, aber diese geheimen Namen werden den API-Clients nicht zurückgegeben.
/// tip | Tipp
So würden Sie **Passwörter** handhaben. Empfangen Sie sie, aber geben Sie sie nicht in der API zurück.
Sie würden auch die Werte der Passwörter **hashen**, bevor Sie sie speichern, und sie **niemals im Klartext** speichern.
///
Die Felder von `HeroCreate` sind:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
#### `HeroUpdate` – das *Datenmodell* zum Aktualisieren eines Helden { #heroupdate-the-data-model-to-update-a-hero }
In der vorherigen Version der App hatten wir keine Möglichkeit, einen Helden **zu aktualisieren**, aber jetzt mit **mehreren Modellen** können wir es. 🎉
Das `HeroUpdate`-*Datenmodell* ist etwas Besonderes, es hat **die selben Felder**, die benötigt werden, um einen neuen Helden zu erstellen, aber alle Felder sind **optional** (sie haben alle einen Defaultwert). Auf diese Weise, wenn Sie einen Helden aktualisieren, können Sie nur die Felder senden, die Sie aktualisieren möchten.
Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Standardwert von `None`), müssen wir sie erneut **deklarieren**.
Wir müssen wirklich nicht von `HeroBase` erben, weil wir alle Felder neu deklarieren. Ich lasse es aus Konsistenzgründen erben, aber das ist nicht notwendig. Es ist mehr eine Frage des persönlichen Geschmacks. 🤷
Die Felder von `HeroUpdate` sind:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
### Mit `HeroCreate` erstellen und ein `HeroPublic` zurückgeben { #create-with-herocreate-and-return-a-heropublic }
Nun, da wir **mehrere Modelle** haben, können wir die Teile der App aktualisieren, die sie verwenden.
Wir empfangen im Request ein `HeroCreate`-*Datenmodell* und daraus erstellen wir ein `Hero`-*Tabellenmodell*.
Dieses neue *Tabellenmodell* `Hero` wird die vom Client gesendeten Felder haben und zusätzlich eine `id`, die von der Datenbank generiert wird.
Dann geben wir das gleiche *Tabellenmodell* `Hero` von der Funktion zurück. Aber da wir das `response_model` mit dem `HeroPublic`-*Datenmodell* deklarieren, wird **FastAPI** `HeroPublic` verwenden, um die Daten zu validieren und zu serialisieren.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *}
/// tip | Tipp
Jetzt verwenden wir `response_model=HeroPublic` anstelle der **Rückgabetyp-Annotation** `-> HeroPublic`, weil der Wert, den wir zurückgeben, tatsächlich *kein* `HeroPublic` ist.
Wenn wir `-> HeroPublic` deklariert hätten, würden Ihr Editor und Linter (zu Recht) reklamieren, dass Sie ein `Hero` anstelle eines `HeroPublic` zurückgeben.
Durch die Deklaration in `response_model` sagen wir **FastAPI**, dass es seine Aufgabe erledigen soll, ohne die Typannotationen und die Hilfe von Ihrem Editor und anderen Tools zu beeinträchtigen.
///
### Helden mit `HeroPublic` lesen { #read-heroes-with-heropublic }
Wir können dasselbe wie zuvor tun, um `Hero`s zu **lesen**, und erneut verwenden wir `response_model=list[HeroPublic]`, um sicherzustellen, dass die Daten ordnungsgemäß validiert und serialisiert werden.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
### Einen einzelnen Helden mit `HeroPublic` lesen { #read-one-hero-with-heropublic }
Wir können einen einzelnen Helden **lesen**:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
### Einen Helden mit `HeroUpdate` aktualisieren { #update-a-hero-with-heroupdate }
Wir können einen Helden **aktualisieren**. Dafür verwenden wir eine HTTP-`PATCH`-Operation.
Und im Code erhalten wir ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> mit allen Daten, die vom Client gesendet wurden, **nur die Daten, die vom Client gesendet wurden**, unter Ausschluss von Werten, die dort nur als Defaultwerte vorhanden wären. Um dies zu tun, verwenden wir `exclude_unset=True`. Das ist der Haupttrick. 🪄
Dann verwenden wir `hero_db.sqlmodel_update(hero_data)`, um die `hero_db` mit den Daten aus `hero_data` zu aktualisieren.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
### Einen Helden wieder löschen { #delete-a-hero-again }
Das **Löschen** eines Helden bleibt ziemlich gleich.
Wir werden dieses Mal nicht dem Wunsch nachgeben, alles zu refaktorisieren. 😅
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
### Die App erneut ausführen { #run-the-app-again }
Sie können die App erneut ausführen:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Wenn Sie zur `/docs`-API-UI gehen, werden Sie sehen, dass sie jetzt aktualisiert ist und nicht mehr erwarten wird, die `id` vom Client beim Erstellen eines Helden zu erhalten, usw.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image02.png">
</div>
## Zusammenfassung { #recap }
Sie können <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a> verwenden, um mit einer SQL-Datenbank zu interagieren und den Code mit *Datenmodellen* und *Tabellenmodellen* zu vereinfachen.
Sie können viel mehr in der **SQLModel**-Dokumentation lernen, es gibt ein längeres Mini-<a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">Tutorial zur Verwendung von SQLModel mit **FastAPI**</a>. 🚀
+6 -6
View File
@@ -1,8 +1,8 @@
# Statische Dateien
# Statische Dateien { #static-files }
Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisch bereitstellen.
## `StaticFiles` verwenden
## `StaticFiles` verwenden { #use-staticfiles }
* Importieren Sie `StaticFiles`.
* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad.
@@ -17,7 +17,7 @@ Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden.
///
### Was ist „Mounten“?
### Was ist „Mounten“ { #what-is-mounting }
„Mounten“ bedeutet das Hinzufügen einer vollständigen „unabhängigen“ Anwendung an einem bestimmten Pfad, die sich dann um die Handhabung aller Unterpfade kümmert.
@@ -25,7 +25,7 @@ Dies unterscheidet sich von der Verwendung eines `APIRouter`, da eine gemountete
Weitere Informationen hierzu finden Sie im [Handbuch für fortgeschrittene Benutzer](../advanced/index.md){.internal-link target=_blank}.
## Einzelheiten
## Einzelheiten { #details }
Das erste `"/static"` bezieht sich auf den Unterpfad, auf dem diese „Unteranwendung“ „gemountet“ wird. Daher wird jeder Pfad, der mit `"/static"` beginnt, von ihr verarbeitet.
@@ -33,8 +33,8 @@ Das `directory="static"` bezieht sich auf den Namen des Verzeichnisses, das Ihre
Das `name="static"` gibt dieser Unteranwendung einen Namen, der intern von **FastAPI** verwendet werden kann.
Alle diese Parameter können anders als "`static`" lauten, passen Sie sie an die Bedürfnisse und spezifischen Details Ihrer eigenen Anwendung an.
Alle diese Parameter können anders als „`static`“ lauten, passen Sie sie an die Bedürfnisse und spezifischen Details Ihrer eigenen Anwendung an.
## Weitere Informationen
## Weitere Informationen { #more-info }
Weitere Details und Optionen finden Sie in der <a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">Dokumentation von Starlette zu statischen Dateien</a>.
+22 -16
View File
@@ -1,18 +1,22 @@
# Testen
# Testen { #testing }
Dank <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a> ist das Testen von **FastAPI**-Anwendungen einfach und macht Spaß.
Es basiert auf <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, welches wiederum auf der Grundlage von requests konzipiert wurde, es ist also sehr vertraut und intuitiv.
Es basiert auf <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, welches wiederum auf der Grundlage von Requests konzipiert wurde, es ist also sehr vertraut und intuitiv.
Damit können Sie <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> direkt mit **FastAPI** verwenden.
## Verwendung von `TestClient`
## `TestClient` verwenden { #using-testclient }
/// info
/// info | Info
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`.
Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie sie und installieren Sie es dann, z. B.:
```console
$ pip install httpx
```
///
@@ -48,17 +52,17 @@ Sie könnten auch `from starlette.testclient import TestClient` verwenden.
/// 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.
Wenn Sie in Ihren Tests neben dem Senden von <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> 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
## Tests separieren { #separating-tests }
In einer echten Anwendung würden Sie Ihre Tests wahrscheinlich in einer anderen Datei haben.
Und Ihre **FastAPI**-Anwendung könnte auch aus mehreren Dateien/Modulen, usw. bestehen.
### **FastAPI** Anwendungsdatei
### **FastAPI** Anwendungsdatei { #fastapi-app-file }
Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigger-applications.md){.internal-link target=_blank} beschrieben:
@@ -75,7 +79,7 @@ In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung:
{* ../../docs_src/app_testing/main.py *}
### Testdatei
### Testdatei { #testing-file }
Dann könnten Sie eine Datei `test_main.py` mit Ihren Tests haben. Sie könnte sich im selben Python-Package befinden (dasselbe Verzeichnis mit einer `__init__.py`-Datei):
@@ -94,11 +98,11 @@ Da sich diese Datei im selben Package befindet, können Sie relative Importe ver
... und haben den Code für die Tests wie zuvor.
## Testen: erweitertes Beispiel
## Testen: erweitertes Beispiel { #testing-extended-example }
Nun erweitern wir dieses Beispiel und fügen weitere Details hinzu, um zu sehen, wie verschiedene Teile getestet werden.
### Erweiterte **FastAPI**-Anwendungsdatei
### Erweiterte **FastAPI**-Anwendungsdatei { #extended-fastapi-app-file }
Fahren wir mit der gleichen Dateistruktur wie zuvor fort:
@@ -170,7 +174,7 @@ Bevorzugen Sie die `Annotated`-Version, falls möglich.
////
### Erweiterte Testdatei
### Erweiterte Testdatei { #extended-testing-file }
Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren:
@@ -184,14 +188,14 @@ Dann machen Sie in Ihren Tests einfach das gleiche.
Z. B.:
* Um einen *Pfad*- oder *Query*-Parameter zu übergeben, fügen Sie ihn der URL selbst hinzu.
* Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein `dict`) an den Parameter `json`.
* Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr>) an den Parameter `json`.
* Wenn Sie *Formulardaten* anstelle von JSON senden müssen, verwenden Sie stattdessen den `data`-Parameter.
* Um *Header* zu übergeben, verwenden Sie ein `dict` im `headers`-Parameter.
* Für *Cookies* ein `dict` im `cookies`-Parameter.
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
/// info | Info
Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
@@ -199,9 +203,11 @@ Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des T
///
## Tests ausführen
## Tests ausführen { #run-it }
Danach müssen Sie nur noch `pytest` installieren:
Danach müssen Sie nur noch `pytest` installieren.
Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie sie und installieren Sie es dann, z. B.:
<div class="termy">