mirror of https://github.com/tiangolo/fastapi.git
Merge branch 'master' into fix_openapi_for_response_model_with_nested_computed_field
This commit is contained in:
commit
62dc326d22
|
|
@ -175,7 +175,7 @@ Sie können denselben `responses`-Parameter verwenden, um verschiedene Medientyp
|
||||||
|
|
||||||
Sie können beispielsweise einen zusätzlichen Medientyp `image/png` hinzufügen und damit deklarieren, dass Ihre *Pfadoperation* ein JSON-Objekt (mit dem Medientyp `application/json`) oder ein PNG-Bild zurückgeben kann:
|
Sie können beispielsweise einen zusätzlichen Medientyp `image/png` hinzufügen und damit deklarieren, dass Ihre *Pfadoperation* ein JSON-Objekt (mit dem Medientyp `application/json`) oder ein PNG-Bild zurückgeben kann:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
|
{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
@ -237,7 +237,7 @@ Mit dieser Technik können Sie einige vordefinierte Responses in Ihren *Pfadoper
|
||||||
|
|
||||||
Zum Beispiel:
|
Zum Beispiel:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
|
{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *}
|
||||||
|
|
||||||
## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses }
|
## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-M
|
||||||
|
|
||||||
Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>:
|
Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *}
|
{* ../../docs_src/dataclasses/tutorial001_py310.py hl[1,6:11,18:19] *}
|
||||||
|
|
||||||
Das ist dank **Pydantic** ebenfalls möglich, da es <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses` intern unterstützt</a>.
|
Das ist dank **Pydantic** ebenfalls möglich, da es <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses` intern unterstützt</a>.
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Tr
|
||||||
|
|
||||||
Sie können `dataclasses` auch im Parameter `response_model` verwenden:
|
Sie können `dataclasses` auch im Parameter `response_model` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial002.py hl[1,7:13,19] *}
|
{* ../../docs_src/dataclasses/tutorial002_py310.py hl[1,6:12,18] *}
|
||||||
|
|
||||||
Die Datenklasse wird automatisch in eine Pydantic-Datenklasse konvertiert.
|
Die Datenklasse wird automatisch in eine Pydantic-Datenklasse konvertiert.
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ In einigen Fällen müssen Sie möglicherweise immer noch Pydantics Version von
|
||||||
|
|
||||||
In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.dataclasses` ersetzen, was einen direkten Ersatz darstellt:
|
In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.dataclasses` ersetzen, was einen direkten Ersatz darstellt:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *}
|
{* ../../docs_src/dataclasses/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *}
|
||||||
|
|
||||||
1. Wir importieren `field` weiterhin von Standard-`dataclasses`.
|
1. Wir importieren `field` weiterhin von Standard-`dataclasses`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Sie verfügt über eine *Pfadoperation*, die einen `Invoice`-Body empfängt, und
|
||||||
|
|
||||||
Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrscheinlich bereits bekannt:
|
Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrscheinlich bereits bekannt:
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehme
|
||||||
|
|
||||||
Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält.
|
Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält.
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
|
||||||
|
|
||||||
### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation }
|
### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation }
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ Sie sollte wie eine normale FastAPI-*Pfadoperation* aussehen:
|
||||||
* Sie sollte wahrscheinlich eine Deklaration des Bodys enthalten, die sie erhalten soll, z. B. `body: InvoiceEvent`.
|
* Sie sollte wahrscheinlich eine Deklaration des Bodys enthalten, die sie erhalten soll, z. B. `body: InvoiceEvent`.
|
||||||
* Und sie könnte auch eine Deklaration der Response enthalten, die zurückgegeben werden soll, z. B. `response_model=InvoiceEventReceived`.
|
* Und sie könnte auch eine Deklaration der Response enthalten, die zurückgegeben werden soll, z. B. `response_model=InvoiceEventReceived`.
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
|
||||||
|
|
||||||
Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*:
|
Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*:
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@ An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejen
|
||||||
|
|
||||||
Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben:
|
Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ Das Hinzufügen eines `\f` (ein maskiertes „Form Feed“-Zeichen) führt dazu,
|
||||||
|
|
||||||
Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) können den Rest verwenden.
|
Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) können den Rest verwenden.
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
|
||||||
|
|
||||||
## Zusätzliche Responses { #additional-responses }
|
## Zusätzliche Responses { #additional-responses }
|
||||||
|
|
||||||
|
|
@ -155,13 +155,13 @@ In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Fu
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
@ -179,13 +179,13 @@ Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[26:33] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Sie können beispielsweise kein Pydantic-Modell in eine `JSONResponse` einfügen
|
||||||
|
|
||||||
In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu konvertieren, bevor Sie sie an eine Response übergeben:
|
In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu konvertieren, bevor Sie sie an eine Response übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *}
|
{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ Dies könnte besonders beim Testen nützlich sein, da es sehr einfach ist, eine
|
||||||
|
|
||||||
Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen:
|
Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app02/config.py hl[10] *}
|
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
|
||||||
|
|
||||||
Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen.
|
Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen.
|
||||||
|
|
||||||
|
|
@ -174,7 +174,7 @@ Und dann können wir das von der *Pfadoperation-Funktion* als Abhängigkeit einf
|
||||||
|
|
||||||
Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt:
|
Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
|
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
|
||||||
|
|
||||||
Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurück.
|
Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurück.
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ Und dann aktualisieren Sie Ihre `config.py` mit:
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/settings/app03_an/config.py hl[9] *}
|
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet.
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/settings/app03_an/config_pv1.py hl[9:10] *}
|
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ FastAPI enthält einige Defaultkonfigurationsparameter, die für die meisten Anw
|
||||||
|
|
||||||
Es umfasst die folgenden Defaultkonfigurationen:
|
Es umfasst die folgenden Defaultkonfigurationen:
|
||||||
|
|
||||||
{* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *}
|
{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *}
|
||||||
|
|
||||||
Sie können jede davon überschreiben, indem Sie im Argument `swagger_ui_parameters` einen anderen Wert festlegen.
|
Sie können jede davon überschreiben, indem Sie im Argument `swagger_ui_parameters` einen anderen Wert festlegen.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ Wenn der Header kein `gzip` enthält, wird nicht versucht, den Body zu dekomprim
|
||||||
|
|
||||||
Auf diese Weise kann dieselbe Routenklasse gzip-komprimierte oder unkomprimierte Requests verarbeiten.
|
Auf diese Weise kann dieselbe Routenklasse gzip-komprimierte oder unkomprimierte Requests verarbeiten.
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *}
|
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}
|
||||||
|
|
||||||
### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class }
|
### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class }
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ Diese Methode gibt eine Funktion zurück. Und diese Funktion empfängt einen <ab
|
||||||
|
|
||||||
Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` zu erstellen.
|
Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` zu erstellen.
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial001.py hl[18:26] *}
|
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -92,18 +92,18 @@ Wir können denselben Ansatz auch verwenden, um in einem Exceptionhandler auf de
|
||||||
|
|
||||||
Alles, was wir tun müssen, ist, den Request innerhalb eines `try`/`except`-Blocks zu handhaben:
|
Alles, was wir tun müssen, ist, den Request innerhalb eines `try`/`except`-Blocks zu handhaben:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[13,15] *}
|
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
|
||||||
|
|
||||||
Wenn eine Exception auftritt, befindet sich die `Request`-Instanz weiterhin im Gültigkeitsbereich, sodass wir den Requestbody lesen und bei der Fehlerbehandlung verwenden können:
|
Wenn eine Exception auftritt, befindet sich die `Request`-Instanz weiterhin im Gültigkeitsbereich, sodass wir den Requestbody lesen und bei der Fehlerbehandlung verwenden können:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *}
|
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}
|
||||||
|
|
||||||
## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router }
|
## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router }
|
||||||
|
|
||||||
Sie können auch den Parameter `route_class` eines `APIRouter` festlegen:
|
Sie können auch den Parameter `route_class` eines `APIRouter` festlegen:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial003.py hl[26] *}
|
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}
|
||||||
|
|
||||||
In diesem Beispiel verwenden die *Pfadoperationen* unter dem `router` die benutzerdefinierte `TimedRoute`-Klasse und haben in der Response einen zusätzlichen `X-Response-Time`-Header mit der Zeit, die zum Generieren der Response benötigt wurde:
|
In diesem Beispiel verwenden die *Pfadoperationen* unter dem `router` die benutzerdefinierte `TimedRoute`-Klasse und haben in der Response einen zusätzlichen `X-Response-Time`-Header mit der Zeit, die zum Generieren der Response benötigt wurde:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial003.py hl[13:20] *}
|
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,18 @@ GitHub-Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-templ
|
||||||
## Full Stack FastAPI Template – Technologiestack und Funktionen { #full-stack-fastapi-template-technology-stack-and-features }
|
## Full Stack FastAPI Template – Technologiestack und Funktionen { #full-stack-fastapi-template-technology-stack-and-features }
|
||||||
|
|
||||||
- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/de) für die Python-Backend-API.
|
- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/de) für die Python-Backend-API.
|
||||||
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) für die Interaktion mit der Python-SQL-Datenbank (ORM).
|
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) für die Interaktion mit der Python-SQL-Datenbank (ORM).
|
||||||
- 🔍 [Pydantic](https://docs.pydantic.dev), verwendet von FastAPI, für die Datenvalidierung und das Einstellungsmanagement.
|
- 🔍 [Pydantic](https://docs.pydantic.dev), verwendet von FastAPI, für die Datenvalidierung und das Einstellungsmanagement.
|
||||||
- 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank.
|
- 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank.
|
||||||
- 🚀 [React](https://react.dev) für das Frontend.
|
- 🚀 [React](https://react.dev) für das Frontend.
|
||||||
- 💃 Verwendung von TypeScript, Hooks, [Vite](https://vitejs.dev) und anderen Teilen eines modernen Frontend-Stacks.
|
- 💃 Verwendung von TypeScript, Hooks, [Vite](https://vitejs.dev) und anderen Teilen eines modernen Frontend-Stacks.
|
||||||
- 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten.
|
- 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten.
|
||||||
- 🤖 Ein automatisch generierter Frontend-Client.
|
- 🤖 Ein automatisch generierter Frontend-Client.
|
||||||
- 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests.
|
- 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests.
|
||||||
- 🦇 Unterstützung des Dunkelmodus.
|
- 🦇 „Dark-Mode“-Unterstützung.
|
||||||
- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion.
|
- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion.
|
||||||
- 🔒 Sicheres Passwort-Hashing standardmäßig.
|
- 🔒 Sicheres Passwort-Hashing standardmäßig.
|
||||||
- 🔑 JWT-Token-Authentifizierung.
|
- 🔑 JWT (JSON Web Token)-Token-Authentifizierung.
|
||||||
- 📫 E-Mail-basierte Passwortwiederherstellung.
|
- 📫 E-Mail-basierte Passwortwiederherstellung.
|
||||||
- ✅ Tests mit [Pytest](https://pytest.org).
|
- ✅ Tests mit [Pytest](https://pytest.org).
|
||||||
- 📞 [Traefik](https://traefik.io) als Reverse-Proxy / Load Balancer.
|
- 📞 [Traefik](https://traefik.io) als Reverse-Proxy / Load Balancer.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# Ressourcen { #resources }
|
# Ressourcen { #resources }
|
||||||
|
|
||||||
Zusätzliche Ressourcen, externe Links, Artikel und mehr. ✈️
|
Zusätzliche Ressourcen, externe Links und mehr. ✈️
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,7 @@ Sie können die *Pfadoperationen* für dieses Modul mit `APIRouter` erstellen.
|
||||||
|
|
||||||
Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`:
|
Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`:
|
||||||
|
|
||||||
```Python hl_lines="1 3" title="app/routers/users.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/routers/users.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter }
|
### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter }
|
||||||
|
|
||||||
|
|
@ -95,9 +93,7 @@ Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren.
|
||||||
|
|
||||||
Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`:
|
Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`:
|
||||||
|
|
||||||
```Python hl_lines="6 11 16" title="app/routers/users.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/routers/users.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
Sie können sich `APIRouter` als eine „Mini-`FastAPI`“-Klasse vorstellen.
|
Sie können sich `APIRouter` als eine „Mini-`FastAPI`“-Klasse vorstellen.
|
||||||
|
|
||||||
|
|
@ -121,35 +117,7 @@ Also fügen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`)
|
||||||
|
|
||||||
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
|
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
||||||
|
|
||||||
```Python hl_lines="3 6-8" title="app/dependencies.py"
|
|
||||||
{!> ../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.8+
|
|
||||||
|
|
||||||
```Python hl_lines="1 5-7" title="app/dependencies.py"
|
|
||||||
{!> ../../docs_src/bigger_applications/app_an/dependencies.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.8+ nicht annotiert
|
|
||||||
|
|
||||||
/// tip | Tipp
|
|
||||||
|
|
||||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
```Python hl_lines="1 4-6" title="app/dependencies.py"
|
|
||||||
{!> ../../docs_src/bigger_applications/app/dependencies.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -181,9 +149,7 @@ Wir wissen, dass alle *Pfadoperationen* in diesem Modul folgendes haben:
|
||||||
|
|
||||||
Anstatt also alles zu jeder *Pfadoperation* hinzuzufügen, können wir es dem `APIRouter` hinzufügen.
|
Anstatt also alles zu jeder *Pfadoperation* hinzuzufügen, können wir es dem `APIRouter` hinzufügen.
|
||||||
|
|
||||||
```Python hl_lines="5-10 16 21" title="app/routers/items.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in:
|
Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in:
|
||||||
|
|
||||||
|
|
@ -242,9 +208,7 @@ Und wir müssen die Abhängigkeitsfunktion aus dem Modul `app.dependencies` impo
|
||||||
|
|
||||||
Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
|
Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
|
||||||
|
|
||||||
```Python hl_lines="3" title="app/routers/items.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Wie relative Importe funktionieren { #how-relative-imports-work }
|
#### Wie relative Importe funktionieren { #how-relative-imports-work }
|
||||||
|
|
||||||
|
|
@ -315,9 +279,7 @@ Wir fügen weder das Präfix `/items` noch `tags=["items"]` zu jeder *Pfadoperat
|
||||||
|
|
||||||
Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *Pfadoperation* angewendet werden, sowie einige zusätzliche `responses`, die speziell für diese *Pfadoperation* gelten:
|
Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *Pfadoperation* angewendet werden, sowie einige zusätzliche `responses`, die speziell für diese *Pfadoperation* gelten:
|
||||||
|
|
||||||
```Python hl_lines="30-31" title="app/routers/items.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -343,17 +305,13 @@ Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse.
|
||||||
|
|
||||||
Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies.md){.internal-link target=_blank} deklarieren, die mit den Abhängigkeiten für jeden `APIRouter` kombiniert werden:
|
Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies.md){.internal-link target=_blank} deklarieren, die mit den Abhängigkeiten für jeden `APIRouter` kombiniert werden:
|
||||||
|
|
||||||
```Python hl_lines="1 3 7" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Den `APIRouter` importieren { #import-the-apirouter }
|
### Den `APIRouter` importieren { #import-the-apirouter }
|
||||||
|
|
||||||
Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
|
Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
|
||||||
|
|
||||||
```Python hl_lines="4-5" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
@ -416,17 +374,13 @@ würde der `router` von `users` den von `items` überschreiben und wir könnten
|
||||||
|
|
||||||
Um also beide in derselben Datei verwenden zu können, importieren wir die Submodule direkt:
|
Um also beide in derselben Datei verwenden zu können, importieren wir die Submodule direkt:
|
||||||
|
|
||||||
```Python hl_lines="5" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Die `APIRouter` für `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items }
|
### 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`:
|
Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
|
||||||
|
|
||||||
```Python hl_lines="10-11" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -466,17 +420,13 @@ Sie enthält einen `APIRouter` mit einigen administrativen *Pfadoperationen*, di
|
||||||
|
|
||||||
In diesem Beispiel wird es ganz einfach sein. Nehmen wir jedoch an, dass wir, da sie mit anderen Projekten in der Organisation geteilt wird, sie nicht ändern und kein `prefix`, `dependencies`, `tags`, usw. direkt zum `APIRouter` hinzufügen können:
|
In diesem Beispiel wird es ganz einfach sein. Nehmen wir jedoch an, dass wir, da sie mit anderen Projekten in der Organisation geteilt wird, sie nicht ändern und kein `prefix`, `dependencies`, `tags`, usw. direkt zum `APIRouter` hinzufügen können:
|
||||||
|
|
||||||
```Python hl_lines="3" title="app/internal/admin.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/internal/admin.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
Aber wir möchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir möchten es mit den `dependencies` sichern, die wir bereits für dieses Projekt haben, und wir möchten `tags` und `responses` hinzufügen.
|
Aber wir möchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir möchten es mit den `dependencies` sichern, die wir bereits für dieses Projekt haben, und wir möchten `tags` und `responses` hinzufügen.
|
||||||
|
|
||||||
Wir können das alles deklarieren, ohne den ursprünglichen `APIRouter` ändern zu müssen, indem wir diese Parameter an `app.include_router()` übergeben:
|
Wir können das alles deklarieren, ohne den ursprünglichen `APIRouter` ändern zu müssen, indem wir diese Parameter an `app.include_router()` übergeben:
|
||||||
|
|
||||||
```Python hl_lines="14-17" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
Auf diese Weise bleibt der ursprüngliche `APIRouter` unverändert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen können.
|
Auf diese Weise bleibt der ursprüngliche `APIRouter` unverändert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen können.
|
||||||
|
|
||||||
|
|
@ -497,9 +447,7 @@ Wir können *Pfadoperationen* auch direkt zur `FastAPI`-App hinzufügen.
|
||||||
|
|
||||||
Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
|
Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
|
||||||
|
|
||||||
```Python hl_lines="21-23" title="app/main.py"
|
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
|
||||||
{!../../docs_src/bigger_applications/app/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
|
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ Ihre API hat jetzt die Macht, ihre eigene <abbr title="Das ist ein Scherz, nur f
|
||||||
|
|
||||||
Sie können die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`):
|
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] *}
|
{* ../../docs_src/cookie_param_models/tutorial002_an_py310.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>**.
|
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>**.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und ve
|
||||||
|
|
||||||
Der Exceptionhandler erhält einen `Request` und die Exception.
|
Der Exceptionhandler erhält einen `Request` und die Exception.
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:19] *}
|
||||||
|
|
||||||
Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit:
|
Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit:
|
||||||
|
|
||||||
|
|
@ -149,36 +149,17 @@ Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen
|
||||||
eine Textversion mit:
|
eine Textversion mit:
|
||||||
|
|
||||||
```
|
```
|
||||||
1 validation error
|
Validation errors:
|
||||||
path -> item_id
|
Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
|
||||||
value is not a valid integer (type=type_error.integer)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `RequestValidationError` vs. `ValidationError` { #requestvalidationerror-vs-validationerror }
|
|
||||||
|
|
||||||
/// warning | Achtung
|
|
||||||
|
|
||||||
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://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
|
||||||
|
|
||||||
**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 wird ihn nicht sehen. Stattdessen erhält der Client einen „Internal Server Error“ mit einem HTTP-Statuscode `500`.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler }
|
### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler }
|
||||||
|
|
||||||
Auf die gleiche Weise 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:
|
Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,25] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -188,6 +169,14 @@ Sie könnten auch `from starlette.responses import PlainTextResponse` verwenden.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
|
/// warning | Achtung
|
||||||
|
|
||||||
|
Beachten Sie, dass der `RequestValidationError` Informationen über den Dateinamen und die Zeile enthält, in der der Validierungsfehler auftritt, sodass Sie ihn bei Bedarf mit den relevanten Informationen in Ihren Logs anzeigen können.
|
||||||
|
|
||||||
|
Das bedeutet aber auch, dass, wenn Sie ihn einfach in einen String umwandeln und diese Informationen direkt zurückgeben, Sie möglicherweise ein paar Informationen über Ihr System preisgeben. Daher extrahiert und zeigt der Code hier jeden Fehler getrennt.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body }
|
### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body }
|
||||||
|
|
||||||
Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten.
|
Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten.
|
||||||
|
|
|
||||||
|
|
@ -122,63 +122,13 @@ Sie verfügt über eine `POST`-Operation, die mehrere Fehler zurückgeben könnt
|
||||||
|
|
||||||
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
|
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
|
||||||
|
|
||||||
//// tab | Python 3.10+
|
{* ../../docs_src/app_testing/app_b_an_py310/main.py *}
|
||||||
|
|
||||||
```Python
|
|
||||||
{!> ../../docs_src/app_testing/app_b_an_py310/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
|
||||||
|
|
||||||
```Python
|
|
||||||
{!> ../../docs_src/app_testing/app_b_an_py39/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.8+
|
|
||||||
|
|
||||||
```Python
|
|
||||||
{!> ../../docs_src/app_testing/app_b_an/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.10+ nicht annotiert
|
|
||||||
|
|
||||||
/// tip | Tipp
|
|
||||||
|
|
||||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
```Python
|
|
||||||
{!> ../../docs_src/app_testing/app_b_py310/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
//// tab | Python 3.8+ nicht annotiert
|
|
||||||
|
|
||||||
/// tip | Tipp
|
|
||||||
|
|
||||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
```Python
|
|
||||||
{!> ../../docs_src/app_testing/app_b/main.py!}
|
|
||||||
```
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
### Erweiterte Testdatei { #extended-testing-file }
|
### Erweiterte Testdatei { #extended-testing-file }
|
||||||
|
|
||||||
Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren:
|
Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/app_b/test_main.py *}
|
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
|
||||||
|
|
||||||
|
|
||||||
Wenn Sie möchten, dass der Client Informationen im Request übergibt und Sie nicht wissen, wie das geht, können Sie suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert.
|
Wenn Sie möchten, dass der Client Informationen im Request übergibt und Sie nicht wissen, wie das geht, können Sie suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert.
|
||||||
|
|
|
||||||
|
|
@ -1,430 +0,0 @@
|
||||||
Articles:
|
|
||||||
English:
|
|
||||||
- author: Apitally
|
|
||||||
author_link: https://apitally.io
|
|
||||||
link: https://apitally.io/blog/getting-started-with-logging-in-fastapi
|
|
||||||
title: Getting started with logging in FastAPI
|
|
||||||
- author: Balthazar Rouberol
|
|
||||||
author_link: https://balthazar-rouberol.com
|
|
||||||
link: https://blog.balthazar-rouberol.com/how-to-profile-a-fastapi-asynchronous-request
|
|
||||||
title: How to profile a FastAPI asynchronous request
|
|
||||||
- author: Stephen Siegert - Neon
|
|
||||||
link: https://neon.tech/blog/deploy-a-serverless-fastapi-app-with-neon-postgres-and-aws-app-runner-at-any-scale
|
|
||||||
title: Deploy a Serverless FastAPI App with Neon Postgres and AWS App Runner at any scale
|
|
||||||
- author: Kurtis Pykes - NVIDIA
|
|
||||||
link: https://developer.nvidia.com/blog/building-a-machine-learning-microservice-with-fastapi/
|
|
||||||
title: Building a Machine Learning Microservice with FastAPI
|
|
||||||
- author: Ravgeet Dhillon - Twilio
|
|
||||||
link: https://www.twilio.com/en-us/blog/booking-appointments-twilio-notion-fastapi
|
|
||||||
title: Booking Appointments with Twilio, Notion, and FastAPI
|
|
||||||
- author: Abhinav Tripathi - Microsoft Blogs
|
|
||||||
link: https://devblogs.microsoft.com/cosmosdb/azure-cosmos-db-python-and-fastapi/
|
|
||||||
title: Write a Python data layer with Azure Cosmos DB and FastAPI
|
|
||||||
- author: Donny Peeters
|
|
||||||
author_link: https://github.com/Donnype
|
|
||||||
link: https://bitestreams.com/blog/fastapi-sqlalchemy/
|
|
||||||
title: 10 Tips for adding SQLAlchemy to FastAPI
|
|
||||||
- author: Jessica Temporal
|
|
||||||
author_link: https://jtemporal.com/socials
|
|
||||||
link: https://jtemporal.com/tips-on-migrating-from-flask-to-fastapi-and-vice-versa/
|
|
||||||
title: Tips on migrating from Flask to FastAPI and vice-versa
|
|
||||||
- author: Ankit Anchlia
|
|
||||||
author_link: https://linkedin.com/in/aanchlia21
|
|
||||||
link: https://hackernoon.com/explore-how-to-effectively-use-jwt-with-fastapi
|
|
||||||
title: Explore How to Effectively Use JWT With FastAPI
|
|
||||||
- author: Nicoló Lino
|
|
||||||
author_link: https://www.nlino.com
|
|
||||||
link: https://github.com/softwarebloat/python-tracing-demo
|
|
||||||
title: Instrument FastAPI with OpenTelemetry tracing and visualize traces in Grafana Tempo.
|
|
||||||
- author: Mikhail Rozhkov, Elena Samuylova
|
|
||||||
author_link: https://www.linkedin.com/in/mnrozhkov/
|
|
||||||
link: https://www.evidentlyai.com/blog/fastapi-tutorial
|
|
||||||
title: ML serving and monitoring with FastAPI and Evidently
|
|
||||||
- author: Visual Studio Code Team
|
|
||||||
author_link: https://code.visualstudio.com/
|
|
||||||
link: https://code.visualstudio.com/docs/python/tutorial-fastapi
|
|
||||||
title: FastAPI Tutorial in Visual Studio Code
|
|
||||||
- author: Apitally
|
|
||||||
author_link: https://apitally.io
|
|
||||||
link: https://blog.apitally.io/fastapi-application-monitoring-made-easy
|
|
||||||
title: FastAPI application monitoring made easy
|
|
||||||
- author: John Philip
|
|
||||||
author_link: https://medium.com/@amjohnphilip
|
|
||||||
link: https://python.plainenglish.io/building-a-restful-api-with-fastapi-secure-signup-and-login-functionality-included-45cdbcb36106
|
|
||||||
title: "Building a RESTful API with FastAPI: Secure Signup and Login Functionality Included"
|
|
||||||
- author: Keshav Malik
|
|
||||||
author_link: https://theinfosecguy.xyz/
|
|
||||||
link: https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide
|
|
||||||
title: Building a CRUD API with FastAPI and Supabase
|
|
||||||
- author: Adejumo Ridwan Suleiman
|
|
||||||
author_link: https://www.linkedin.com/in/adejumoridwan/
|
|
||||||
link: https://medium.com/python-in-plain-english/build-an-sms-spam-classifier-serverless-database-with-faunadb-and-fastapi-23dbb275bc5b
|
|
||||||
title: Build an SMS Spam Classifier Serverless Database with FaunaDB and FastAPI
|
|
||||||
- author: Raf Rasenberg
|
|
||||||
author_link: https://rafrasenberg.com/about/
|
|
||||||
link: https://rafrasenberg.com/fastapi-lambda/
|
|
||||||
title: 'FastAPI lambda container: serverless simplified'
|
|
||||||
- author: Teresa N. Fontanella De Santis
|
|
||||||
author_link: https://dev.to/
|
|
||||||
link: https://dev.to/teresafds/authorization-on-fastapi-with-casbin-41og
|
|
||||||
title: Authorization on FastAPI with Casbin
|
|
||||||
- author: New Relic
|
|
||||||
author_link: https://newrelic.com
|
|
||||||
link: https://newrelic.com/instant-observability/fastapi/e559ec64-f765-4470-a15f-1901fcebb468
|
|
||||||
title: How to monitor FastAPI application performance using Python agent
|
|
||||||
- author: Jean-Baptiste Rocher
|
|
||||||
author_link: https://hashnode.com/@jibrocher
|
|
||||||
link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app
|
|
||||||
title: Building the Poll App From Django Tutorial With FastAPI And React
|
|
||||||
- author: Silvan Melchior
|
|
||||||
author_link: https://github.com/silvanmelchior
|
|
||||||
link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12
|
|
||||||
title: Seamless FastAPI Configuration with ConfZ
|
|
||||||
- author: Kaustubh Gupta
|
|
||||||
author_link: https://medium.com/@kaustubhgupta1828/
|
|
||||||
link: https://levelup.gitconnected.com/5-advance-features-of-fastapi-you-should-try-7c0ac7eebb3e
|
|
||||||
title: 5 Advanced Features of FastAPI You Should Try
|
|
||||||
- author: Kaustubh Gupta
|
|
||||||
author_link: https://medium.com/@kaustubhgupta1828/
|
|
||||||
link: https://www.analyticsvidhya.com/blog/2021/06/deploying-ml-models-as-api-using-fastapi-and-heroku/
|
|
||||||
title: Deploying ML Models as API Using FastAPI and Heroku
|
|
||||||
- link: https://jarmos.netlify.app/posts/using-github-actions-to-deploy-a-fastapi-project-to-heroku/
|
|
||||||
title: Using GitHub Actions to Deploy a FastAPI Project to Heroku
|
|
||||||
author_link: https://jarmos.netlify.app/
|
|
||||||
author: Somraj Saha
|
|
||||||
- author: "@pystar"
|
|
||||||
author_link: https://pystar.substack.com/
|
|
||||||
link: https://pystar.substack.com/p/how-to-create-a-fake-certificate
|
|
||||||
title: How to Create A Fake Certificate Authority And Generate TLS Certs for FastAPI
|
|
||||||
- author: Ben Gamble
|
|
||||||
author_link: https://uk.linkedin.com/in/bengamble7
|
|
||||||
link: https://ably.com/blog/realtime-ticket-booking-solution-kafka-fastapi-ably
|
|
||||||
title: Building a realtime ticket booking solution with Kafka, FastAPI, and Ably
|
|
||||||
- author: Shahriyar(Shako) Rzayev
|
|
||||||
author_link: https://www.linkedin.com/in/shahriyar-rzayev/
|
|
||||||
link: https://www.azepug.az/posts/fastapi/#building-simple-e-commerce-with-nuxtjs-and-fastapi-series
|
|
||||||
title: Building simple E-Commerce with NuxtJS and FastAPI
|
|
||||||
- author: Rodrigo Arenas
|
|
||||||
author_link: https://rodrigo-arenas.medium.com/
|
|
||||||
link: https://medium.com/analytics-vidhya/serve-a-machine-learning-model-using-sklearn-fastapi-and-docker-85aabf96729b
|
|
||||||
title: "Serve a machine learning model using Sklearn, FastAPI and Docker"
|
|
||||||
- author: Yashasvi Singh
|
|
||||||
author_link: https://hashnode.com/@aUnicornDev
|
|
||||||
link: https://aunicorndev.hashnode.dev/series/supafast-api
|
|
||||||
title: "Building an API with FastAPI and Supabase and Deploying on Deta"
|
|
||||||
- author: Navule Pavan Kumar Rao
|
|
||||||
author_link: https://www.linkedin.com/in/navule/
|
|
||||||
link: https://www.tutlinks.com/deploy-fastapi-on-ubuntu-gunicorn-caddy-2/
|
|
||||||
title: Deploy FastAPI on Ubuntu and Serve using Caddy 2 Web Server
|
|
||||||
- author: Patrick Ladon
|
|
||||||
author_link: https://dev.to/factorlive
|
|
||||||
link: https://dev.to/factorlive/python-facebook-messenger-webhook-with-fastapi-on-glitch-4n90
|
|
||||||
title: Python Facebook messenger webhook with FastAPI on Glitch
|
|
||||||
- author: Valon Januzaj
|
|
||||||
author_link: https://www.linkedin.com/in/valon-januzaj-b02692187/
|
|
||||||
link: https://valonjanuzaj.medium.com/deploy-a-dockerized-fastapi-application-to-aws-cc757830ba1b
|
|
||||||
title: Deploy a dockerized FastAPI application to AWS
|
|
||||||
- author: Amit Chaudhary
|
|
||||||
author_link: https://x.com/amitness
|
|
||||||
link: https://amitness.com/2020/06/fastapi-vs-flask/
|
|
||||||
title: FastAPI for Flask Users
|
|
||||||
- author: Louis Guitton
|
|
||||||
author_link: https://x.com/louis_guitton
|
|
||||||
link: https://guitton.co/posts/fastapi-monitoring/
|
|
||||||
title: How to monitor your FastAPI service
|
|
||||||
- author: Precious Ndubueze
|
|
||||||
author_link: https://medium.com/@gabbyprecious2000
|
|
||||||
link: https://medium.com/@gabbyprecious2000/creating-a-crud-app-with-fastapi-part-one-7c049292ad37
|
|
||||||
title: Creating a CRUD App with FastAPI (Part one)
|
|
||||||
- author: Farhad Malik
|
|
||||||
author_link: https://medium.com/@farhadmalik
|
|
||||||
link: https://towardsdatascience.com/build-and-host-fast-data-science-applications-using-fastapi-823be8a1d6a0
|
|
||||||
title: Build And Host Fast Data Science Applications Using FastAPI
|
|
||||||
- author: Navule Pavan Kumar Rao
|
|
||||||
author_link: https://www.linkedin.com/in/navule/
|
|
||||||
link: https://www.tutlinks.com/deploy-fastapi-on-azure/
|
|
||||||
title: Deploy FastAPI on Azure App Service
|
|
||||||
- author: Davide Fiocco
|
|
||||||
author_link: https://github.com/davidefiocco
|
|
||||||
link: https://davidefiocco.github.io/streamlit-fastapi-ml-serving/
|
|
||||||
title: Machine learning model serving in Python using FastAPI and streamlit
|
|
||||||
- author: Netflix
|
|
||||||
author_link: https://netflixtechblog.com/
|
|
||||||
link: https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072
|
|
||||||
title: Introducing Dispatch
|
|
||||||
- author: Stavros Korokithakis
|
|
||||||
author_link: https://x.com/Stavros
|
|
||||||
link: https://www.stavros.io/posts/fastapi-with-django/
|
|
||||||
title: Using FastAPI with Django
|
|
||||||
- author: Twilio
|
|
||||||
author_link: https://www.twilio.com
|
|
||||||
link: https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi
|
|
||||||
title: Build a Secure Twilio Webhook with Python and FastAPI
|
|
||||||
- author: Sebastián Ramírez (tiangolo)
|
|
||||||
author_link: https://x.com/tiangolo
|
|
||||||
link: https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe
|
|
||||||
title: Build a web API from scratch with FastAPI - the workshop
|
|
||||||
- author: Paul Sec
|
|
||||||
author_link: https://x.com/PaulWebSec
|
|
||||||
link: https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/
|
|
||||||
title: FastAPI + Zeit.co = 🚀
|
|
||||||
- author: cuongld2
|
|
||||||
author_link: https://dev.to/cuongld2
|
|
||||||
link: https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o
|
|
||||||
title: Build simple API service with Python FastAPI — Part 1
|
|
||||||
- author: Paurakh Sharma Humagain
|
|
||||||
author_link: https://x.com/PaurakhSharma
|
|
||||||
link: https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc
|
|
||||||
title: Microservice in Python using FastAPI
|
|
||||||
- author: Guillermo Cruz
|
|
||||||
author_link: https://wuilly.com/
|
|
||||||
link: https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/
|
|
||||||
title: Real-time Notifications with Python and Postgres
|
|
||||||
- author: Navule Pavan Kumar Rao
|
|
||||||
author_link: https://www.linkedin.com/in/navule/
|
|
||||||
link: https://www.tutlinks.com/create-and-deploy-fastapi-app-to-heroku/
|
|
||||||
title: Create and Deploy FastAPI app to Heroku without using Docker
|
|
||||||
- author: Arthur Henrique
|
|
||||||
author_link: https://x.com/arthurheinrique
|
|
||||||
link: https://medium.com/@arthur393/another-boilerplate-to-fastapi-azure-pipeline-ci-pytest-3c8d9a4be0bb
|
|
||||||
title: 'Another Boilerplate to FastAPI: Azure Pipeline CI + Pytest'
|
|
||||||
- author: Shane Soh
|
|
||||||
author_link: https://medium.com/@shane.soh
|
|
||||||
link: https://medium.com/analytics-vidhya/deploy-machine-learning-models-with-keras-fastapi-redis-and-docker-4940df614ece
|
|
||||||
title: Deploy Machine Learning Models with Keras, FastAPI, Redis and Docker
|
|
||||||
- author: Mandy Gu
|
|
||||||
author_link: https://towardsdatascience.com/@mandygu
|
|
||||||
link: https://towardsdatascience.com/deploying-iris-classifications-with-fastapi-and-docker-7c9b83fdec3a
|
|
||||||
title: 'Towards Data Science: Deploying Iris Classifications with FastAPI and Docker'
|
|
||||||
- author: Michael Herman
|
|
||||||
author_link: https://testdriven.io/authors/herman
|
|
||||||
link: https://testdriven.io/blog/fastapi-crud/
|
|
||||||
title: 'TestDriven.io: Developing and Testing an Asynchronous API with FastAPI and Pytest'
|
|
||||||
- author: Bernard Brenyah
|
|
||||||
author_link: https://medium.com/@bbrenyah
|
|
||||||
link: https://medium.com/python-data/how-to-deploy-tensorflow-2-0-models-as-an-api-service-with-fastapi-docker-128b177e81f3
|
|
||||||
title: How To Deploy Tensorflow 2.0 Models As An API Service With FastAPI & Docker
|
|
||||||
- author: Dylan Anthony
|
|
||||||
author_link: https://dev.to/dbanty
|
|
||||||
link: https://dev.to/dbanty/why-i-m-leaving-flask-3ki6
|
|
||||||
title: Why I'm Leaving Flask
|
|
||||||
- author: Mike Moritz
|
|
||||||
author_link: https://medium.com/@mike.p.moritz
|
|
||||||
link: https://medium.com/@mike.p.moritz/using-docker-compose-to-deploy-a-lightweight-python-rest-api-with-a-job-queue-37e6072a209b
|
|
||||||
title: Using Docker Compose to deploy a lightweight Python REST API with a job queue
|
|
||||||
- author: '@euri10'
|
|
||||||
author_link: https://gitlab.com/euri10
|
|
||||||
link: https://gitlab.com/euri10/fastapi_cheatsheet
|
|
||||||
title: A FastAPI and Swagger UI visual cheatsheet
|
|
||||||
- author: Uber Engineering
|
|
||||||
author_link: https://eng.uber.com
|
|
||||||
link: https://eng.uber.com/ludwig-v0-2/
|
|
||||||
title: 'Uber: Ludwig v0.2 Adds New Features and Other Improvements to its Deep Learning Toolbox [including a FastAPI server]'
|
|
||||||
- author: Maarten Grootendorst
|
|
||||||
author_link: https://www.linkedin.com/in/mgrootendorst/
|
|
||||||
link: https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-dc51200fe8cf
|
|
||||||
title: How to Deploy a Machine Learning Model
|
|
||||||
- author: Johannes Gontrum
|
|
||||||
author_link: https://x.com/gntrm
|
|
||||||
link: https://medium.com/@gntrm/jwt-authentication-with-fastapi-and-aws-cognito-1333f7f2729e
|
|
||||||
title: JWT Authentication with FastAPI and AWS Cognito
|
|
||||||
- author: Ankush Thakur
|
|
||||||
author_link: https://geekflare.com/author/ankush/
|
|
||||||
link: https://geekflare.com/python-asynchronous-web-frameworks/
|
|
||||||
title: Top 5 Asynchronous Web Frameworks for Python
|
|
||||||
- author: Nico Axtmann
|
|
||||||
author_link: https://www.linkedin.com/in/nico-axtmann
|
|
||||||
link: https://medium.com/@nico.axtmann95/deploying-a-scikit-learn-model-with-onnx-und-fastapi-1af398268915
|
|
||||||
title: Deploying a scikit-learn model with ONNX and FastAPI
|
|
||||||
- author: Nils de Bruin
|
|
||||||
author_link: https://medium.com/@nilsdebruin
|
|
||||||
link: https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680
|
|
||||||
title: 'FastAPI authentication revisited: Enabling API key authentication'
|
|
||||||
- author: Nick Cortale
|
|
||||||
author_link: https://nickc1.github.io/
|
|
||||||
link: https://nickc1.github.io/api,/scikit-learn/2019/01/10/scikit-fastapi.html
|
|
||||||
title: 'FastAPI and Scikit-Learn: Easily Deploy Models'
|
|
||||||
- author: Errieta Kostala
|
|
||||||
author_link: https://dev.to/errietta
|
|
||||||
link: https://dev.to/errietta/introduction-to-the-fastapi-python-framework-2n10
|
|
||||||
title: Introduction to the fastapi python framework
|
|
||||||
- author: Nils de Bruin
|
|
||||||
author_link: https://medium.com/@nilsdebruin
|
|
||||||
link: https://medium.com/data-rebels/fastapi-how-to-add-basic-and-cookie-authentication-a45c85ef47d3
|
|
||||||
title: FastAPI — How to add basic and cookie authentication
|
|
||||||
- author: Nils de Bruin
|
|
||||||
author_link: https://medium.com/@nilsdebruin
|
|
||||||
link: https://medium.com/data-rebels/fastapi-google-as-an-external-authentication-provider-3a527672cf33
|
|
||||||
title: FastAPI — Google as an external authentication provider
|
|
||||||
- author: William Hayes
|
|
||||||
author_link: https://medium.com/@williamhayes
|
|
||||||
link: https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59
|
|
||||||
title: FastAPI/Starlette debug vs prod
|
|
||||||
- author: Mukul Mantosh
|
|
||||||
author_link: https://x.com/MantoshMukul
|
|
||||||
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
|
|
||||||
title: Developing FastAPI Application using K8s & AWS
|
|
||||||
- author: KrishNa
|
|
||||||
author_link: https://medium.com/@krishnardt365
|
|
||||||
link: https://medium.com/@krishnardt365/fastapi-docker-and-postgres-91943e71be92
|
|
||||||
title: Fastapi, Docker(Docker compose) and Postgres
|
|
||||||
- author: Devon Ray
|
|
||||||
author_link: https://devonray.com
|
|
||||||
link: https://devonray.com/blog/deploying-a-fastapi-project-using-aws-lambda-aurora-cdk
|
|
||||||
title: Deployment using Docker, Lambda, Aurora, CDK & GH Actions
|
|
||||||
- author: Shubhendra Kushwaha
|
|
||||||
author_link: https://www.linkedin.com/in/theshubhendra/
|
|
||||||
link: https://theshubhendra.medium.com/mastering-soft-delete-advanced-sqlalchemy-techniques-4678f4738947
|
|
||||||
title: 'Mastering Soft Delete: Advanced SQLAlchemy Techniques'
|
|
||||||
- author: Shubhendra Kushwaha
|
|
||||||
author_link: https://www.linkedin.com/in/theshubhendra/
|
|
||||||
link: https://theshubhendra.medium.com/role-based-row-filtering-advanced-sqlalchemy-techniques-733e6b1328f6
|
|
||||||
title: 'Role based row filtering: Advanced SQLAlchemy Techniques'
|
|
||||||
German:
|
|
||||||
- author: Marcel Sander (actidoo)
|
|
||||||
author_link: https://www.actidoo.com
|
|
||||||
link: https://www.actidoo.com/de/blog/python-fastapi-domain-driven-design
|
|
||||||
title: Domain-driven Design mit Python und FastAPI
|
|
||||||
- author: Nico Axtmann
|
|
||||||
author_link: https://x.com/_nicoax
|
|
||||||
link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/
|
|
||||||
title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI
|
|
||||||
- author: Felix Schürmeyer
|
|
||||||
author_link: https://hellocoding.de/autor/felix-schuermeyer/
|
|
||||||
link: https://hellocoding.de/blog/coding-language/python/fastapi
|
|
||||||
title: REST-API Programmieren mittels Python und dem FastAPI Modul
|
|
||||||
Japanese:
|
|
||||||
- author: '@bee2'
|
|
||||||
author_link: https://qiita.com/bee2
|
|
||||||
link: https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9
|
|
||||||
title: '[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する'
|
|
||||||
- author: '@bee2'
|
|
||||||
author_link: https://qiita.com/bee2
|
|
||||||
link: https://qiita.com/bee2/items/0ad260ab9835a2087dae
|
|
||||||
title: PythonのWeb frameworkのパフォーマンス比較 (Django, Flask, responder, FastAPI, japronto)
|
|
||||||
- author: ライトコードメディア編集部
|
|
||||||
author_link: https://rightcode.co.jp/author/jun
|
|
||||||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-admin-page-improvement
|
|
||||||
title: '【第4回】FastAPIチュートリアル: toDoアプリを作ってみよう【管理者ページ改良編】'
|
|
||||||
- author: ライトコードメディア編集部
|
|
||||||
author_link: https://rightcode.co.jp/author/jun
|
|
||||||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-authentication-user-registration
|
|
||||||
title: '【第3回】FastAPIチュートリアル: toDoアプリを作ってみよう【認証・ユーザ登録編】'
|
|
||||||
- author: ライトコードメディア編集部
|
|
||||||
author_link: https://rightcode.co.jp/author/jun
|
|
||||||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-model-building
|
|
||||||
title: '【第2回】FastAPIチュートリアル: ToDoアプリを作ってみよう【モデル構築編】'
|
|
||||||
- author: ライトコードメディア編集部
|
|
||||||
author_link: https://rightcode.co.jp/author/jun
|
|
||||||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-environment
|
|
||||||
title: '【第1回】FastAPIチュートリアル: ToDoアプリを作ってみよう【環境構築編】'
|
|
||||||
- author: Hikaru Takahashi
|
|
||||||
author_link: https://qiita.com/hikarut
|
|
||||||
link: https://qiita.com/hikarut/items/b178af2e2440c67c6ac4
|
|
||||||
title: フロントエンド開発者向けのDockerによるPython開発環境構築
|
|
||||||
- author: '@angel_katayoku'
|
|
||||||
author_link: https://qiita.com/angel_katayoku
|
|
||||||
link: https://qiita.com/angel_katayoku/items/8a458a8952f50b73f420
|
|
||||||
title: FastAPIでPOSTされたJSONのレスポンスbodyを受け取る
|
|
||||||
- author: '@angel_katayoku'
|
|
||||||
author_link: https://qiita.com/angel_katayoku
|
|
||||||
link: https://qiita.com/angel_katayoku/items/4fbc1a4e2b33fa2237d2
|
|
||||||
title: FastAPIをMySQLと接続してDockerで管理してみる
|
|
||||||
- author: '@angel_katayoku'
|
|
||||||
author_link: https://qiita.com/angel_katayoku
|
|
||||||
link: https://qiita.com/angel_katayoku/items/0e1f5dbbe62efc612a78
|
|
||||||
title: FastAPIでCORSを回避
|
|
||||||
- author: '@ryoryomaru'
|
|
||||||
author_link: https://qiita.com/ryoryomaru
|
|
||||||
link: https://qiita.com/ryoryomaru/items/59958ed385b3571d50de
|
|
||||||
title: python製の最新APIフレームワーク FastAPI を触ってみた
|
|
||||||
- author: '@mtitg'
|
|
||||||
author_link: https://qiita.com/mtitg
|
|
||||||
link: https://qiita.com/mtitg/items/47770e9a562dd150631d
|
|
||||||
title: FastAPI|DB接続してCRUDするPython製APIサーバーを構築
|
|
||||||
Portuguese:
|
|
||||||
- author: Eduardo Mendes
|
|
||||||
author_link: https://bolha.us/@dunossauro
|
|
||||||
link: https://fastapidozero.dunossauro.com/
|
|
||||||
title: FastAPI do ZERO
|
|
||||||
- author: Jessica Temporal
|
|
||||||
author_link: https://jtemporal.com/socials
|
|
||||||
link: https://jtemporal.com/dicas-para-migrar-de-flask-para-fastapi-e-vice-versa/
|
|
||||||
title: Dicas para migrar uma aplicação de Flask para FastAPI e vice-versa
|
|
||||||
Russian:
|
|
||||||
- author: Troy Köhler
|
|
||||||
author_link: https://www.linkedin.com/in/trkohler/
|
|
||||||
link: https://trkohler.com/fast-api-introduction-to-framework
|
|
||||||
title: 'FastAPI: знакомимся с фреймворком'
|
|
||||||
- author: prostomarkeloff
|
|
||||||
author_link: https://github.com/prostomarkeloff
|
|
||||||
link: https://habr.com/ru/post/478620/
|
|
||||||
title: Почему Вы должны попробовать FastAPI?
|
|
||||||
- author: Andrey Korchak
|
|
||||||
author_link: https://habr.com/ru/users/57uff3r/
|
|
||||||
link: https://habr.com/ru/post/454440/
|
|
||||||
title: 'Мелкая питонячая радость #2: Starlette - Солидная примочка – FastAPI'
|
|
||||||
Vietnamese:
|
|
||||||
- author: Nguyễn Nhân
|
|
||||||
author_link: https://fullstackstation.com/author/figonking/
|
|
||||||
link: https://fullstackstation.com/fastapi-trien-khai-bang-docker/
|
|
||||||
title: 'FASTAPI: TRIỂN KHAI BẰNG DOCKER'
|
|
||||||
Taiwanese:
|
|
||||||
- author: Leon
|
|
||||||
author_link: http://editor.leonh.space/
|
|
||||||
link: https://editor.leonh.space/2022/tortoise/
|
|
||||||
title: 'Tortoise ORM / FastAPI 整合快速筆記'
|
|
||||||
Spanish:
|
|
||||||
- author: Eduardo Zepeda
|
|
||||||
author_link: https://coffeebytes.dev/en/authors/eduardo-zepeda/
|
|
||||||
link: https://coffeebytes.dev/es/python-fastapi-el-mejor-framework-de-python/
|
|
||||||
title: 'Tutorial de FastAPI, ¿el mejor framework de Python?'
|
|
||||||
Podcasts:
|
|
||||||
English:
|
|
||||||
- author: Behind the Commit
|
|
||||||
author_link: https://www.youtube.com/@BehindtheCommit
|
|
||||||
link: https://youtu.be/iaDRYUQ0OMM
|
|
||||||
title: Why FastAPI Became Python’s Fastest‑Growing Framework – Chat with Sebastián Ramírez
|
|
||||||
- author: Real Python
|
|
||||||
author_link: https://realpython.com/
|
|
||||||
link: https://realpython.com/podcasts/rpp/72/
|
|
||||||
title: Starting With FastAPI and Examining Python's Import System - Episode 72
|
|
||||||
- author: Python Bytes FM
|
|
||||||
author_link: https://pythonbytes.fm/
|
|
||||||
link: https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/
|
|
||||||
title: 'Do you dare to press "."? - Episode 247 - Dan #6: SQLModel - use the same models for SQL and FastAPI'
|
|
||||||
- author: Podcast.`__init__`
|
|
||||||
author_link: https://www.pythonpodcast.com/
|
|
||||||
link: https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/
|
|
||||||
title: Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)
|
|
||||||
- author: Python Bytes FM
|
|
||||||
author_link: https://pythonbytes.fm/
|
|
||||||
link: https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855
|
|
||||||
title: FastAPI on PythonBytes
|
|
||||||
Talks:
|
|
||||||
English:
|
|
||||||
- author: Sebastián Ramírez (tiangolo)
|
|
||||||
author_link: https://x.com/tiangolo
|
|
||||||
link: https://www.youtube.com/watch?v=mwvmfl8nN_U
|
|
||||||
title: 'Keynote: Behind the scenes of FastAPI and friends for developers and builders — Sebastián Ramírez'
|
|
||||||
- author: Jeny Sadadia
|
|
||||||
author_link: https://github.com/JenySadadia
|
|
||||||
link: https://www.youtube.com/watch?v=uZdTe8_Z6BQ
|
|
||||||
title: 'PyCon AU 2023: Testing asynchronous applications with FastAPI and pytest'
|
|
||||||
- author: Sebastián Ramírez (tiangolo)
|
|
||||||
author_link: https://x.com/tiangolo
|
|
||||||
link: https://www.youtube.com/watch?v=PnpTY1f4k2U
|
|
||||||
title: '[VIRTUAL] Py.Amsterdam''s flying Software Circus: Intro to FastAPI'
|
|
||||||
- author: Sebastián Ramírez (tiangolo)
|
|
||||||
author_link: https://x.com/tiangolo
|
|
||||||
link: https://www.youtube.com/watch?v=z9K5pwb0rt8
|
|
||||||
title: 'PyConBY 2020: Serve ML models easily with FastAPI'
|
|
||||||
- author: Chris Withers
|
|
||||||
author_link: https://x.com/chriswithers13
|
|
||||||
link: https://www.youtube.com/watch?v=3DLwPcrE5mA
|
|
||||||
title: 'PyCon UK 2019: FastAPI from the ground up'
|
|
||||||
Taiwanese:
|
|
||||||
- author: Blueswen
|
|
||||||
author_link: https://github.com/blueswen
|
|
||||||
link: https://www.youtube.com/watch?v=y3sumuoDq4w
|
|
||||||
title: 'PyCon TW 2024: 全方位強化 Python 服務可觀測性:以 FastAPI 和 Grafana Stack 為例'
|
|
||||||
|
|
@ -1,36 +1,22 @@
|
||||||
# External Links and Articles
|
# External Links
|
||||||
|
|
||||||
**FastAPI** has a great community constantly growing.
|
**FastAPI** has a great community constantly growing.
|
||||||
|
|
||||||
There are many posts, articles, tools, and projects, related to **FastAPI**.
|
There are many posts, articles, tools, and projects, related to **FastAPI**.
|
||||||
|
|
||||||
Here's an incomplete list of some of them.
|
You could easily use a search engine or video platform to find many resources related to FastAPI.
|
||||||
|
|
||||||
/// tip
|
/// info
|
||||||
|
|
||||||
If you have an article, project, tool, or anything related to **FastAPI** that is not yet listed here, create a <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request adding it</a>.
|
Before, this page used to list links to external articles.
|
||||||
|
|
||||||
|
But now that FastAPI is the backend framework with the most GitHub stars across languages, and the most starred and used framework in Python, it no longer makes sense to attempt to list all articles written about it.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
{% for section_name, section_content in external_links.items() %}
|
|
||||||
|
|
||||||
## {{ section_name }}
|
|
||||||
|
|
||||||
{% for lang_name, lang_content in section_content.items() %}
|
|
||||||
|
|
||||||
### {{ lang_name }}
|
|
||||||
|
|
||||||
{% for item in lang_content %}
|
|
||||||
|
|
||||||
* <a href="{{ item.link }}" class="external-link" target="_blank">{{ item.title }}</a> by <a href="{{ item.author_link }}" class="external-link" target="_blank">{{ item.author }}</a>.
|
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
## GitHub Repositories
|
## GitHub Repositories
|
||||||
|
|
||||||
Most starred GitHub repositories with the topic `fastapi`:
|
Most starred <a href="https://github.com/topics/fastapi" class="external-link" target="_blank">GitHub repositories with the topic `fastapi`</a>:
|
||||||
|
|
||||||
{% for repo in topic_repos %}
|
{% for repo in topic_repos %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,27 @@ hide:
|
||||||
|
|
||||||
### Docs
|
### Docs
|
||||||
|
|
||||||
|
* 📝 Update docs about re-raising validation errors, do not include string as is to not leak information. PR [#14487](https://github.com/fastapi/fastapi/pull/14487) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔥 Remove external links section. PR [#14486](https://github.com/fastapi/fastapi/pull/14486) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
* 🌐 Sync German docs. PR [#14488](https://github.com/fastapi/fastapi/pull/14488) by [@nilslindemann](https://github.com/nilslindemann).
|
||||||
|
|
||||||
|
## 0.124.2
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* 🐛 Fix support for `if TYPE_CHECKING`, non-evaluated stringified annotations. PR [#14485](https://github.com/fastapi/fastapi/pull/14485) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
## 0.124.1
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* 🐛 Fix handling arbitrary types when using `arbitrary_types_allowed=True`. PR [#14482](https://github.com/fastapi/fastapi/pull/14482) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
|
||||||
* 📝 Add variants for code examples in "Advanced User Guide". PR [#14413](https://github.com/fastapi/fastapi/pull/14413) by [@YuriiMotov](https://github.com/YuriiMotov).
|
* 📝 Add variants for code examples in "Advanced User Guide". PR [#14413](https://github.com/fastapi/fastapi/pull/14413) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||||
* 📝 Update tech stack in project generation docs. PR [#14472](https://github.com/fastapi/fastapi/pull/14472) by [@alejsdev](https://github.com/alejsdev).
|
* 📝 Update tech stack in project generation docs. PR [#14472](https://github.com/fastapi/fastapi/pull/14472) by [@alejsdev](https://github.com/alejsdev).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# Resources { #resources }
|
# Resources { #resources }
|
||||||
|
|
||||||
Additional resources, external links, articles and more. ✈️
|
Additional resources, external links, and more. ✈️
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ To override it, import the `RequestValidationError` and use it with `@app.except
|
||||||
|
|
||||||
The exception handler will receive a `Request` and the exception.
|
The exception handler will receive a `Request` and the exception.
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:19] *}
|
||||||
|
|
||||||
Now, if you go to `/items/foo`, instead of getting the default JSON error with:
|
Now, if you go to `/items/foo`, instead of getting the default JSON error with:
|
||||||
|
|
||||||
|
|
@ -149,36 +149,17 @@ Now, if you go to `/items/foo`, instead of getting the default JSON error with:
|
||||||
you will get a text version, with:
|
you will get a text version, with:
|
||||||
|
|
||||||
```
|
```
|
||||||
1 validation error
|
Validation errors:
|
||||||
path -> item_id
|
Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
|
||||||
value is not a valid integer (type=type_error.integer)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `RequestValidationError` vs `ValidationError` { #requestvalidationerror-vs-validationerror }
|
|
||||||
|
|
||||||
/// warning
|
|
||||||
|
|
||||||
These are technical details that you might skip if it's not important for you now.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
`RequestValidationError` is a sub-class of Pydantic's <a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
|
||||||
|
|
||||||
**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
|
|
||||||
|
|
||||||
But the client/user will not see it. Instead, the client will receive an "Internal Server Error" with an HTTP status code `500`.
|
|
||||||
|
|
||||||
It should be this way because if you have a Pydantic `ValidationError` in your *response* or anywhere in your code (not in the client's *request*), it's actually a bug in your code.
|
|
||||||
|
|
||||||
And while you fix it, your clients/users shouldn't have access to internal information about the error, as that could expose a security vulnerability.
|
|
||||||
|
|
||||||
### Override the `HTTPException` error handler { #override-the-httpexception-error-handler }
|
### Override the `HTTPException` error handler { #override-the-httpexception-error-handler }
|
||||||
|
|
||||||
The same way, you can override the `HTTPException` handler.
|
The same way, you can override the `HTTPException` handler.
|
||||||
|
|
||||||
For example, you could want to return a plain text response instead of JSON for these errors:
|
For example, you could want to return a plain text response instead of JSON for these errors:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,25] *}
|
||||||
|
|
||||||
/// note | Technical Details
|
/// note | Technical Details
|
||||||
|
|
||||||
|
|
@ -188,6 +169,14 @@ You could also use `from starlette.responses import PlainTextResponse`.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
Have in mind that the `RequestValidationError` contains the information of the file name and line where the validation error happens so that you can show it in your logs with the relevant information if you want to.
|
||||||
|
|
||||||
|
But that means that if you just convert it to a string and return that information directly, you could be leaking a bit of information about your system, that's why here the code extracts and shows each error independently.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
### Use the `RequestValidationError` body { #use-the-requestvalidationerror-body }
|
### Use the `RequestValidationError` body { #use-the-requestvalidationerror-body }
|
||||||
|
|
||||||
The `RequestValidationError` contains the `body` it received with invalid data.
|
The `RequestValidationError` contains the `body` it received with invalid data.
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ plugins:
|
||||||
search: null
|
search: null
|
||||||
macros:
|
macros:
|
||||||
include_yaml:
|
include_yaml:
|
||||||
- external_links: ../en/data/external_links.yml
|
|
||||||
- github_sponsors: ../en/data/github_sponsors.yml
|
- github_sponsors: ../en/data/github_sponsors.yml
|
||||||
- people: ../en/data/people.yml
|
- people: ../en/data/people.yml
|
||||||
- contributors: ../en/data/contributors.yml
|
- contributors: ../en/data/contributors.yml
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,11 @@ async def http_exception_handler(request, exc):
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(RequestValidationError)
|
@app.exception_handler(RequestValidationError)
|
||||||
async def validation_exception_handler(request, exc):
|
async def validation_exception_handler(request, exc: RequestValidationError):
|
||||||
return PlainTextResponse(str(exc), status_code=400)
|
message = "Validation errors:"
|
||||||
|
for error in exc.errors():
|
||||||
|
message += f"\nField: {error['loc']}, Error: {error['msg']}"
|
||||||
|
return PlainTextResponse(message, status_code=400)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||||
|
|
||||||
__version__ = "0.124.0"
|
__version__ = "0.124.2"
|
||||||
|
|
||||||
from starlette import status as status
|
from starlette import status as status
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
from copy import copy, deepcopy
|
from copy import copy, deepcopy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, is_dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
|
@ -18,7 +18,7 @@ from typing import (
|
||||||
from fastapi._compat import may_v1, shared
|
from fastapi._compat import may_v1, shared
|
||||||
from fastapi.openapi.constants import REF_TEMPLATE
|
from fastapi.openapi.constants import REF_TEMPLATE
|
||||||
from fastapi.types import IncEx, ModelNameMap, UnionType
|
from fastapi.types import IncEx, ModelNameMap, UnionType
|
||||||
from pydantic import BaseModel, TypeAdapter, create_model
|
from pydantic import BaseModel, ConfigDict, TypeAdapter, create_model
|
||||||
from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError
|
from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError
|
||||||
from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation
|
from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation
|
||||||
from pydantic import ValidationError as ValidationError
|
from pydantic import ValidationError as ValidationError
|
||||||
|
|
@ -64,6 +64,7 @@ class ModelField:
|
||||||
field_info: FieldInfo
|
field_info: FieldInfo
|
||||||
name: str
|
name: str
|
||||||
mode: Literal["validation", "serialization"] = "validation"
|
mode: Literal["validation", "serialization"] = "validation"
|
||||||
|
config: Union[ConfigDict, None] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def alias(self) -> str:
|
def alias(self) -> str:
|
||||||
|
|
@ -94,8 +95,14 @@ class ModelField:
|
||||||
warnings.simplefilter(
|
warnings.simplefilter(
|
||||||
"ignore", category=UnsupportedFieldAttributeWarning
|
"ignore", category=UnsupportedFieldAttributeWarning
|
||||||
)
|
)
|
||||||
|
annotated_args = (
|
||||||
|
self.field_info.annotation,
|
||||||
|
*self.field_info.metadata,
|
||||||
|
self.field_info,
|
||||||
|
)
|
||||||
self._type_adapter: TypeAdapter[Any] = TypeAdapter(
|
self._type_adapter: TypeAdapter[Any] = TypeAdapter(
|
||||||
Annotated[self.field_info.annotation, self.field_info]
|
Annotated[annotated_args],
|
||||||
|
config=self.config,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_default(self) -> Any:
|
def get_default(self) -> Any:
|
||||||
|
|
@ -418,10 +425,21 @@ def create_body_model(
|
||||||
|
|
||||||
|
|
||||||
def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
|
def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
|
||||||
return [
|
model_fields: List[ModelField] = []
|
||||||
ModelField(field_info=field_info, name=name)
|
for name, field_info in model.model_fields.items():
|
||||||
for name, field_info in model.model_fields.items()
|
type_ = field_info.annotation
|
||||||
]
|
if lenient_issubclass(type_, (BaseModel, dict)) or is_dataclass(type_):
|
||||||
|
model_config = None
|
||||||
|
else:
|
||||||
|
model_config = model.model_config
|
||||||
|
model_fields.append(
|
||||||
|
ModelField(
|
||||||
|
field_info=field_info,
|
||||||
|
name=name,
|
||||||
|
config=model_config,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return model_fields
|
||||||
|
|
||||||
|
|
||||||
# Duplicate of several schema functions from Pydantic v1 to make them compatible with
|
# Duplicate of several schema functions from Pydantic v1 to make them compatible with
|
||||||
|
|
|
||||||
|
|
@ -209,11 +209,21 @@ def get_flat_params(dependant: Dependant) -> List[ModelField]:
|
||||||
return path_params + query_params + header_params + cookie_params
|
return path_params + query_params + header_params + cookie_params
|
||||||
|
|
||||||
|
|
||||||
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
def _get_signature(call: Callable[..., Any]) -> inspect.Signature:
|
||||||
if sys.version_info >= (3, 10):
|
if sys.version_info >= (3, 10):
|
||||||
signature = inspect.signature(call, eval_str=True)
|
try:
|
||||||
|
signature = inspect.signature(call, eval_str=True)
|
||||||
|
except NameError:
|
||||||
|
# Handle type annotations with if TYPE_CHECKING, not used by FastAPI
|
||||||
|
# e.g. dependency return types
|
||||||
|
signature = inspect.signature(call)
|
||||||
else:
|
else:
|
||||||
signature = inspect.signature(call)
|
signature = inspect.signature(call)
|
||||||
|
return signature
|
||||||
|
|
||||||
|
|
||||||
|
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
||||||
|
signature = _get_signature(call)
|
||||||
unwrapped = inspect.unwrap(call)
|
unwrapped = inspect.unwrap(call)
|
||||||
globalns = getattr(unwrapped, "__globals__", {})
|
globalns = getattr(unwrapped, "__globals__", {})
|
||||||
typed_params = [
|
typed_params = [
|
||||||
|
|
@ -239,10 +249,7 @@ def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
|
||||||
|
|
||||||
|
|
||||||
def get_typed_return_annotation(call: Callable[..., Any]) -> Any:
|
def get_typed_return_annotation(call: Callable[..., Any]) -> Any:
|
||||||
if sys.version_info >= (3, 10):
|
signature = _get_signature(call)
|
||||||
signature = inspect.signature(call, eval_str=True)
|
|
||||||
else:
|
|
||||||
signature = inspect.signature(call)
|
|
||||||
unwrapped = inspect.unwrap(call)
|
unwrapped = inspect.unwrap(call)
|
||||||
annotation = signature.return_annotation
|
annotation = signature.return_annotation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from inline_snapshot import snapshot
|
||||||
|
from typing_extensions import Annotated
|
||||||
|
|
||||||
|
from .utils import needs_pydanticv2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="client")
|
||||||
|
def get_client():
|
||||||
|
from pydantic import (
|
||||||
|
BaseModel,
|
||||||
|
ConfigDict,
|
||||||
|
PlainSerializer,
|
||||||
|
TypeAdapter,
|
||||||
|
WithJsonSchema,
|
||||||
|
)
|
||||||
|
|
||||||
|
class FakeNumpyArray:
|
||||||
|
def __init__(self):
|
||||||
|
self.data = [1.0, 2.0, 3.0]
|
||||||
|
|
||||||
|
FakeNumpyArrayPydantic = Annotated[
|
||||||
|
FakeNumpyArray,
|
||||||
|
WithJsonSchema(TypeAdapter(List[float]).json_schema()),
|
||||||
|
PlainSerializer(lambda v: v.data),
|
||||||
|
]
|
||||||
|
|
||||||
|
class MyModel(BaseModel):
|
||||||
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||||
|
custom_field: FakeNumpyArrayPydantic
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def test() -> MyModel:
|
||||||
|
return MyModel(custom_field=FakeNumpyArray())
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
@needs_pydanticv2
|
||||||
|
def test_get(client: TestClient):
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.json() == {"custom_field": [1.0, 2.0, 3.0]}
|
||||||
|
|
||||||
|
|
||||||
|
@needs_pydanticv2
|
||||||
|
def test_typeadapter():
|
||||||
|
# This test is only to confirm that Pydantic alone is working as expected
|
||||||
|
from pydantic import (
|
||||||
|
BaseModel,
|
||||||
|
ConfigDict,
|
||||||
|
PlainSerializer,
|
||||||
|
TypeAdapter,
|
||||||
|
WithJsonSchema,
|
||||||
|
)
|
||||||
|
|
||||||
|
class FakeNumpyArray:
|
||||||
|
def __init__(self):
|
||||||
|
self.data = [1.0, 2.0, 3.0]
|
||||||
|
|
||||||
|
FakeNumpyArrayPydantic = Annotated[
|
||||||
|
FakeNumpyArray,
|
||||||
|
WithJsonSchema(TypeAdapter(List[float]).json_schema()),
|
||||||
|
PlainSerializer(lambda v: v.data),
|
||||||
|
]
|
||||||
|
|
||||||
|
class MyModel(BaseModel):
|
||||||
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||||
|
custom_field: FakeNumpyArrayPydantic
|
||||||
|
|
||||||
|
ta = TypeAdapter(MyModel)
|
||||||
|
assert ta.dump_python(MyModel(custom_field=FakeNumpyArray())) == {
|
||||||
|
"custom_field": [1.0, 2.0, 3.0]
|
||||||
|
}
|
||||||
|
assert ta.json_schema() == snapshot(
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"custom_field": {
|
||||||
|
"items": {"type": "number"},
|
||||||
|
"title": "Custom Field",
|
||||||
|
"type": "array",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["custom_field"],
|
||||||
|
"title": "MyModel",
|
||||||
|
"type": "object",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@needs_pydanticv2
|
||||||
|
def test_openapi_schema(client: TestClient):
|
||||||
|
response = client.get("openapi.json")
|
||||||
|
assert response.json() == snapshot(
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||||
|
"paths": {
|
||||||
|
"/": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Test",
|
||||||
|
"operationId": "test__get",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/MyModel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"MyModel": {
|
||||||
|
"properties": {
|
||||||
|
"custom_field": {
|
||||||
|
"items": {"type": "number"},
|
||||||
|
"type": "array",
|
||||||
|
"title": "Custom Field",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"required": ["custom_field"],
|
||||||
|
"title": "MyModel",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from fastapi import Depends, FastAPI
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from inline_snapshot import snapshot
|
||||||
|
from typing_extensions import Annotated
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from collections.abc import AsyncGenerator
|
||||||
|
|
||||||
|
|
||||||
|
class DummyClient:
|
||||||
|
async def get_people(self) -> list:
|
||||||
|
return ["John Doe", "Jane Doe"]
|
||||||
|
|
||||||
|
async def close(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def get_client() -> AsyncGenerator[DummyClient, None]:
|
||||||
|
client = DummyClient()
|
||||||
|
yield client
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
|
||||||
|
Client = Annotated[DummyClient, Depends(get_client)]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="client")
|
||||||
|
def client_fixture() -> TestClient:
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
async def get_people(client: Client) -> list:
|
||||||
|
return await client.get_people()
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
def test_get(client: TestClient):
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200, response.text
|
||||||
|
assert response.json() == ["John Doe", "Jane Doe"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_openapi_schema(client: TestClient):
|
||||||
|
response = client.get("/openapi.json")
|
||||||
|
assert response.status_code == 200, response.text
|
||||||
|
assert response.json() == snapshot(
|
||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||||
|
"paths": {
|
||||||
|
"/": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get People",
|
||||||
|
"operationId": "get_people__get",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {},
|
||||||
|
"type": "array",
|
||||||
|
"title": "Response Get People Get",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -8,18 +8,8 @@ client = TestClient(app)
|
||||||
def test_get_validation_error():
|
def test_get_validation_error():
|
||||||
response = client.get("/items/foo")
|
response = client.get("/items/foo")
|
||||||
assert response.status_code == 400, response.text
|
assert response.status_code == 400, response.text
|
||||||
# TODO: remove when deprecating Pydantic v1
|
assert "Validation errors:" in response.text
|
||||||
assert (
|
assert "Field: ('path', 'item_id')" in response.text
|
||||||
# TODO: remove when deprecating Pydantic v1
|
|
||||||
"path -> item_id" in response.text
|
|
||||||
or "'loc': ('path', 'item_id')" in response.text
|
|
||||||
)
|
|
||||||
assert (
|
|
||||||
# TODO: remove when deprecating Pydantic v1
|
|
||||||
"value is not a valid integer" in response.text
|
|
||||||
or "Input should be a valid integer, unable to parse string as an integer"
|
|
||||||
in response.text
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_http_error():
|
def test_get_http_error():
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue