Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot]
6135c77139 🌐 Update translations for ru (update-outdated) 2026-02-05 16:00:35 +00:00
43 changed files with 288 additions and 634 deletions

View File

@@ -35,11 +35,6 @@ on:
type: boolean
required: false
default: false
max:
description: Maximum number of items to translate (e.g. 10)
type: number
required: false
default: 10
jobs:
langs:
@@ -120,4 +115,3 @@ jobs:
EN_PATH: ${{ github.event.inputs.en_path }}
COMMAND: ${{ matrix.command }}
COMMIT_IN_PLACE: ${{ github.event.inputs.commit_in_place }}
MAX: ${{ github.event.inputs.max }}

View File

@@ -6,29 +6,13 @@ Dazu können Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wr
## `WSGIMiddleware` verwenden { #using-wsgimiddleware }
/// info | Info
Dafür muss `a2wsgi` installiert sein, z. B. mit `pip install a2wsgi`.
///
Sie müssen `WSGIMiddleware` aus `a2wsgi` importieren.
Sie müssen `WSGIMiddleware` importieren.
Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware.
Und dann mounten Sie das auf einem Pfad.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | Hinweis
Früher wurde empfohlen, `WSGIMiddleware` aus `fastapi.middleware.wsgi` zu verwenden, dies ist jetzt deprecatet.
Stattdessen wird empfohlen, das Paket `a2wsgi` zu verwenden. Die Nutzung bleibt gleich.
Stellen Sie lediglich sicher, dass das Paket `a2wsgi` installiert ist und importieren Sie `WSGIMiddleware` korrekt aus `a2wsgi`.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Es testen { #check-it }

View File

@@ -145,6 +145,8 @@ Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhän
* Erstellen Sie eine `main.py`-Datei mit:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -156,7 +158,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```

View File

@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
Erstellen Sie eine Datei `main.py` mit:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
Wenn Ihr Code `async` / `await` verwendet, benutzen Sie `async def`:
```Python hl_lines="7 12"
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -284,7 +288,9 @@ Sie sehen die alternative automatische Dokumentation (bereitgestellt von <a href
Deklarieren Sie den Body mit Standard-Python-Typen, dank Pydantic.
```Python hl_lines="2 7-10 23-25"
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool | None = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}

View File

@@ -1,6 +1,6 @@
# Body Mehrere Parameter { #body-multiple-parameters }
Nun, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von <abbr title="Requestbody">Requestbody</abbr>-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 { #mix-path-query-and-body-parameters }
@@ -101,13 +101,13 @@ Natürlich können Sie auch, wann immer Sie das brauchen, weitere Query-Paramete
Da einfache Werte standardmäßig als Query-Parameter interpretiert werden, müssen Sie `Query` nicht explizit hinzufügen, Sie können einfach schreiben:
```Python
q: str | None = None
q: Union[str, None] = None
```
Oder in Python 3.9:
Oder in Python 3.10 und darüber:
```Python
q: Union[str, None] = None
q: str | None = None
```
Zum Beispiel:

View File

@@ -52,7 +52,7 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern.
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[17:18] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## Beschreibung mittels Docstring { #description-from-docstring }
@@ -70,7 +70,7 @@ Es wird in der interaktiven Dokumentation verwendet:
Sie können die Response mit dem Parameter `response_description` beschreiben:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info | Info

View File

@@ -7,17 +7,6 @@ hide:
## Latest Changes
## 0.128.2
### Features
* ✨ Add support for PEP695 `TypeAliasType`. PR [#13920](https://github.com/fastapi/fastapi/pull/13920) by [@cstruct](https://github.com/cstruct).
* ✨ Allow `Response` type hint as dependency annotation. PR [#14794](https://github.com/fastapi/fastapi/pull/14794) by [@jonathan-fulton](https://github.com/jonathan-fulton).
### Fixes
* 🐛 Fix using `Json[list[str]]` type (issue #10997). PR [#14616](https://github.com/fastapi/fastapi/pull/14616) by [@mkanetsuna](https://github.com/mkanetsuna).
### Docs
* 📝 Update docs for translations. PR [#14830](https://github.com/fastapi/fastapi/pull/14830) by [@tiangolo](https://github.com/tiangolo).
@@ -25,24 +14,12 @@ hide:
### Translations
* 🌐 Enable Traditional Chinese translations. PR [#14842](https://github.com/fastapi/fastapi/pull/14842) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Enable French docs translations. PR [#14841](https://github.com/fastapi/fastapi/pull/14841) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for fr (translate-page). PR [#14837](https://github.com/fastapi/fastapi/pull/14837) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🔨 Add max pages to translate to configs. PR [#14840](https://github.com/fastapi/fastapi/pull/14840) by [@tiangolo](https://github.com/tiangolo).
## 0.128.1
### Features

View File

@@ -317,8 +317,6 @@ extra:
name: de - Deutsch
- link: /es/
name: es - español
- link: /fr/
name: fr - français
- link: /ja/
name: ja - 日本語
- link: /ko/
@@ -331,8 +329,6 @@ extra:
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /zh-hant/
name: zh-hant - 繁體中文
extra_css:
- css/termynal.css
- css/custom.css

View File

@@ -2,33 +2,17 @@
Puedes montar aplicaciones WSGI como viste con [Sub Aplicaciones - Mounts](sub-applications.md){.internal-link target=_blank}, [Detrás de un Proxy](behind-a-proxy.md){.internal-link target=_blank}.
Para eso, puedes usar el `WSGIMiddleware` y usarlo para envolver tu aplicación WSGI, por ejemplo, Flask, Django, etc.
Para eso, puedes usar `WSGIMiddleware` y usarlo para envolver tu aplicación WSGI, por ejemplo, Flask, Django, etc.
## Usando `WSGIMiddleware` { #using-wsgimiddleware }
/// info | Información
Esto requiere instalar `a2wsgi`, por ejemplo con `pip install a2wsgi`.
///
Necesitas importar `WSGIMiddleware` de `a2wsgi`.
Necesitas importar `WSGIMiddleware`.
Luego envuelve la aplicación WSGI (p. ej., Flask) con el middleware.
Y luego móntala bajo un path.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | Nota
Anteriormente, se recomendaba usar `WSGIMiddleware` de `fastapi.middleware.wsgi`, pero ahora está deprecado.
Se aconseja usar el paquete `a2wsgi` en su lugar. El uso sigue siendo el mismo.
Solo asegúrate de tener instalado el paquete `a2wsgi` e importar `WSGIMiddleware` correctamente desde `a2wsgi`.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Revisa { #check-it }

View File

@@ -145,6 +145,8 @@ Existen otros formatos y herramientas para definir e instalar dependencias de pa
* Crea un archivo `main.py` con:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -156,7 +158,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -570,7 +572,7 @@ Si tienes una configuración simple, con un **contenedor único** que luego inic
### Imagen Base de Docker { #base-docker-image }
Solía haber una imagen official de Docker de FastAPI: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Pero ahora está obsoleta. ⛔️
Solía haber una imagen official de Docker de FastAPI: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi-docker</a>. Pero ahora está obsoleta. ⛔️
Probablemente **no** deberías usar esta imagen base de Docker (o cualquier otra similar).

View File

@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
Crea un archivo `main.py` con:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
Si tu código usa `async` / `await`, usa `async def`:
```Python hl_lines="7 12"
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -284,7 +288,9 @@ Ahora modifica el archivo `main.py` para recibir un body desde un request `PUT`.
Declara el body usando tipos estándar de Python, gracias a Pydantic.
```Python hl_lines="2 7-10 23-25"
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool | None = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}

View File

@@ -101,13 +101,13 @@ Por supuesto, también puedes declarar parámetros adicionales de query siempre
Como, por defecto, los valores singulares se interpretan como parámetros de query, no tienes que añadir explícitamente un `Query`, solo puedes hacer:
```Python
q: str | None = None
q: Union[str, None] = None
```
O en Python 3.9:
O en Python 3.10 y superior:
```Python
q: Union[str, None] = None
q: str | None = None
```
Por ejemplo:

View File

@@ -52,7 +52,7 @@ En estos casos, podría tener sentido almacenar las tags en un `Enum`.
Puedes añadir un `summary` y `description`:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## Descripción desde docstring { #description-from-docstring }
@@ -70,7 +70,7 @@ Será usado en la documentación interactiva:
Puedes especificar la descripción del response con el parámetro `response_description`:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info | Información

View File

@@ -1,82 +1,33 @@
# Exécuter un serveur manuellement { #run-a-server-manually }
# Exécuter un serveur manuellement - Uvicorn
## Utiliser la commande `fastapi run` { #use-the-fastapi-run-command }
La principale chose dont vous avez besoin pour exécuter une application **FastAPI** sur une machine serveur distante est un programme serveur ASGI tel que **Uvicorn**.
En bref, utilisez `fastapi run` pour servir votre application FastAPI :
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting production 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://0.0.0.0: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://0.0.0.0:8000/docs</u></font>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>2306215</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.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
```
</div>
Cela fonctionnerait pour la plupart des cas. 😎
Vous pourriez utiliser cette commande par exemple pour démarrer votre application **FastAPI** dans un conteneur, sur un serveur, etc.
## Serveurs ASGI { #asgi-servers }
Allons un peu plus en détail.
FastAPI utilise un standard pour construire des frameworks web Python et des serveurs appelé <abbr title="Asynchronous Server Gateway Interface - Interface passerelle serveur asynchrone">ASGI</abbr>. FastAPI est un framework web ASGI.
La principale chose dont vous avez besoin pour exécuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui utilisé par défaut par la commande `fastapi`.
Il existe plusieurs alternatives, notamment :
Il existe 3 principales alternatives :
* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> : un serveur ASGI haute performance.
* <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a> : un serveur ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalités.
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a> : le serveur ASGI conçu pour Django Channels.
* <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a> : un serveur HTTP Rust pour les applications Python.
* <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a> : NGINX Unit est un environnement d'exécution d'applications web léger et polyvalent.
* <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a> : un serveur
ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalités.
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a> : le serveur ASGI
conçu pour Django Channels.
## Machine serveur et programme serveur { #server-machine-and-server-program }
## Machine serveur et programme serveur
Il y a un petit détail sur les noms à garder à l'esprit. 💡
Le mot « serveur » est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn).
Le mot "**serveur**" est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn).
Gardez cela à l'esprit lorsque vous lisez « serveur » en général, cela pourrait faire référence à l'une de ces deux choses.
Gardez cela à l'esprit lorsque vous lisez "serveur" en général, cela pourrait faire référence à l'une de ces deux choses.
Lorsqu'on se réfère à la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nœud**. Tout cela fait référence à un type de machine distante, exécutant normalement Linux, sur laquelle vous exécutez des programmes.
Lorsqu'on se réfère à la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nœud**. Tout cela fait référence à un type de machine distante, exécutant Linux, en règle générale, sur laquelle vous exécutez des programmes.
## Installer le programme serveur { #install-the-server-program }
Lorsque vous installez FastAPI, il est fourni avec un serveur de production, Uvicorn, et vous pouvez le démarrer avec la commande `fastapi run`.
## Installer le programme serveur
Mais vous pouvez également installer un serveur ASGI manuellement.
Vous pouvez installer un serveur compatible ASGI avec :
Vous devez créer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, puis vous pouvez installer l'application serveur.
//// tab | Uvicorn
Par exemple, pour installer Uvicorn :
* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>, un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
<div class="termy">
@@ -88,21 +39,39 @@ $ pip install "uvicorn[standard]"
</div>
Un processus similaire s'appliquerait à tout autre programme de serveur ASGI.
/// tip | Astuce
En ajoutant `standard`, Uvicorn va installer et utiliser quelques dépendances supplémentaires recommandées.
Cela inclut `uvloop`, le remplaçant hautes performances de `asyncio`, qui fournit le gros gain de performance en matière de concurrence.
Lorsque vous installez FastAPI avec quelque chose comme `pip install "fastapi[standard]"`, vous obtenez déjà `uvicorn[standard]` aussi.
Cela inclut `uvloop`, le remplaçant performant de `asyncio`, qui fournit le gros gain de performance en matière de concurrence.
///
## Exécuter le programme serveur { #run-the-server-program }
////
Si vous avez installé un serveur ASGI manuellement, vous devrez normalement passer une chaîne d'import dans un format spécial pour qu'il importe votre application FastAPI :
//// tab | Hypercorn
* <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, un serveur ASGI également compatible avec HTTP/2.
<div class="termy">
```console
$ pip install hypercorn
---> 100%
```
</div>
...ou tout autre serveur ASGI.
////
## Exécutez le programme serveur
Vous pouvez ensuite exécuter votre application de la même manière que vous l'avez fait dans les tutoriels, mais sans l'option `--reload`, par exemple :
//// tab | Uvicorn
<div class="termy">
@@ -114,44 +83,85 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
</div>
/// note | Remarque
////
La commande `uvicorn main:app` fait référence à :
//// tab | Hypercorn
* `main` : le fichier `main.py` (le « module » Python).
* `app` : l'objet créé dans `main.py` avec la ligne `app = FastAPI()`.
<div class="termy">
C'est équivalent à :
```console
$ hypercorn main:app --bind 0.0.0.0:80
```Python
from main import app
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
```
///
</div>
Chaque programme de serveur ASGI alternatif aurait une commande similaire, vous pouvez en lire plus dans leur documentation respective.
////
/// warning | Alertes
/// warning
Uvicorn et d'autres serveurs prennent en charge une option `--reload` utile pendant le développement.
N'oubliez pas de supprimer l'option `--reload` si vous l'utilisiez.
L'option `--reload` consomme beaucoup plus de ressources, est plus instable, etc.
L'option `--reload` consomme beaucoup plus de ressources, est plus instable, etc.
Cela aide beaucoup pendant le **développement**, mais vous **ne devriez pas** l'utiliser en **production**.
Cela aide beaucoup pendant le **développement**, mais vous **ne devriez pas** l'utiliser en **production**.
///
## Concepts de déploiement { #deployment-concepts }
## Hypercorn avec Trio
Ces exemples exécutent le programme serveur (par exemple Uvicorn), en démarrant **un seul processus**, à l'écoute sur toutes les IP (`0.0.0.0`) sur un port prédéfini (par exemple `80`).
Starlette et **FastAPI** sont basés sur
<a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, qui les rend
compatibles avec <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a>, de la bibliothèque standard Python et
<a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
C'est l'idée de base. Mais vous voudrez probablement vous occuper de certaines choses supplémentaires, comme :
Néanmoins, Uvicorn n'est actuellement compatible qu'avec asyncio, et il utilise normalement <a href="https://github.
com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a >, le remplaçant hautes performances de `asyncio`.
* Sécurité - HTTPS
* Exécution au démarrage
* Redémarrages
* Réplication (le nombre de processus en cours d'exécution)
* Mémoire
* Étapes précédant le démarrage
Mais si vous souhaitez utiliser directement **Trio**, vous pouvez utiliser **Hypercorn** car il le prend en charge. ✨
Je vous en dirai plus sur chacun de ces concepts, sur la manière d'y réfléchir, et donnerai quelques exemples concrets avec des stratégies pour les gérer dans les prochains chapitres. 🚀
### Installer Hypercorn avec Trio
Vous devez d'abord installer Hypercorn avec le support Trio :
<div class="termy">
```console
$ pip install "hypercorn[trio]"
---> 100%
```
</div>
### Exécuter avec Trio
Ensuite, vous pouvez passer l'option de ligne de commande `--worker-class` avec la valeur `trio` :
<div class="termy">
```console
$ hypercorn main:app --worker-class trio
```
</div>
Et cela démarrera Hypercorn avec votre application en utilisant Trio comme backend.
Vous pouvez désormais utiliser Trio en interne dans votre application. Ou mieux encore, vous pouvez utiliser AnyIO pour que votre code reste compatible avec Trio et asyncio. 🎉
## Concepts de déploiement
Ces exemples lancent le programme serveur (e.g. Uvicorn), démarrant **un seul processus**, sur toutes les IPs (`0.0.
0.0`) sur un port prédéfini (par example, `80`).
C'est l'idée de base. Mais vous vous préoccuperez probablement de certains concepts supplémentaires, tels que ... :
* la sécurité - HTTPS
* l'exécution au démarrage
* les redémarrages
* la réplication (le nombre de processus en cours d'exécution)
* la mémoire
* les étapes précédant le démarrage
Je vous en dirai plus sur chacun de ces concepts, sur la façon de les aborder, et donnerai quelques exemples concrets avec des stratégies pour les traiter dans les prochains chapitres. 🚀

View File

@@ -79,13 +79,13 @@ checker(q="somequery")
### `yield`와 `scope`가 있는 의존성 { #dependencies-with-yield-and-scope }
0.121.0 버전에서 FastAPI는 `Depends(scope="function")` 지원을 추가했습니다.
0.121.0 버전에서 FastAPI는 `yield`가 있는 의존성에 대해 `Depends(scope="function")` 지원을 추가했습니다.
`Depends(scope="function")`를 사용하면, `yield` 이후의 종료 코드는 *경로 처리 함수*가 끝난 직후(클라이언트에 응답이 반환되기 전)에 실행됩니다.
그리고 `Depends(scope="request")`(기본값)를 사용하면, `yield` 이후의 종료 코드는 응답이 전송된 후에 실행됩니다.
자세한 내용은 [`yield`가 있는 의존성 - 조기 종료와 `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) 문서를 참고하세요.
자세한 내용은 [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) 문서를 참고하세요.
### `yield`가 있는 의존성과 `StreamingResponse`, 기술 세부사항 { #dependencies-with-yield-and-streamingresponse-technical-details }
@@ -133,7 +133,7 @@ SQLModel(또는 SQLAlchemy)을 사용하면서 이런 특정 사용 사례가
그러면 세션이 데이터베이스 연결을 해제하여, 다른 요청들이 이를 사용할 수 있게 됩니다.
`yield`가 있는 의존성에서 조기 종료가 필요한 다른 사용 사례가 있다면, 여러분의 구체적인 사용 사례와 `yield`가 있는 의존성에 대한 조기 종료가 어떤 점에서 이득이 되는지를 포함해 <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions 질문</a>을 생성해 주세요.
`yield`가 있는 의존성에서 조기 종료가 필요한 다른 사용 사례가 있다면, 여러분의 구체적인 사용 사례와 `yield`가 있는 의존성에 대한 조기 종료가 어떤 점에서 이득이 되는지를 포함해 <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussion Question</a>을 생성해 주세요.
`yield`가 있는 의존성에서 조기 종료에 대한 설득력 있는 사용 사례가 있다면, 조기 종료를 선택적으로 활성화할 수 있는 새로운 방법을 추가하는 것을 고려하겠습니다.
@@ -145,7 +145,7 @@ FastAPI 0.110.0 이전에는 `yield`가 있는 의존성을 사용한 다음 그
### 백그라운드 태스크와 `yield`가 있는 의존성, 기술 세부사항 { #background-tasks-and-dependencies-with-yield-technical-details }
FastAPI 0.106.0 이전에는 `yield` 이후에 예외를 발생시키는 것이 불가능했습니다. `yield`가 있는 의존성의 종료 코드는 응답이 전송된 *후에* 실행되었기 때문에, [예외 핸들러](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}가 이미 실행된 뒤였습니다.
FastAPI 0.106.0 이전에는 `yield` 이후에 예외를 발생시키는 것이 불가능했습니다. `yield`가 있는 의존성의 종료 코드는 응답이 전송된 *후에* 실행되었기 때문에, [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}가 이미 실행된 뒤였습니다.
이는 주로 백그라운드 태스크 안에서 의존성이 "yield"한 동일한 객체들을 사용할 수 있게 하기 위한 설계였습니다. 백그라운드 태스크가 끝난 뒤에 종료 코드가 실행되었기 때문입니다.

View File

@@ -1,48 +1,32 @@
# WSGI 포함하기 - Flask, Django { #including-wsgi-flask-django-others }
# WSGI 포함하기 - Flask, Django 그 외 { #including-wsgi-flask-django-others }
[서브 애플리케이션 - 마운트](sub-applications.md){.internal-link target=_blank}, [프록시 뒤에서](behind-a-proxy.md){.internal-link target=_blank}에서 본 것처럼 WSGI 애플리케이션을 마운트할 수 있습니다.
[서브 응용 프로그램 - 마운트](sub-applications.md){.internal-link target=_blank}, [프록시 뒤에서](behind-a-proxy.md){.internal-link target=_blank}에서 보았듯이 WSGI 응용 프로그램들을 마운트 할 수 있습니다.
이를 위해 `WSGIMiddleware`를 사용해 WSGI 애플리케이션(예: Flask, Django 등)을 감쌀 수 있습니다.
이를 위해 `WSGIMiddleware`를 사용해 WSGI 응용 프로그램(예: Flask, Django 등)을 감쌀 수 있습니다.
## `WSGIMiddleware` 사용하기 { #using-wsgimiddleware }
/// info | 정보
`WSGIMiddleware`를 불러와야 합니다.
이를 사용하려면 `a2wsgi`를 설치해야 합니다. 예: `pip install a2wsgi`
그런 다음, WSGI(예: Flask) 응용 프로그램을 미들웨어로 포장합니다.
///
그 후, 해당 경로에 마운트합니다.
`a2wsgi`에서 `WSGIMiddleware`를 import 해야 합니다.
그런 다음, WSGI(예: Flask) 애플리케이션을 미들웨어로 감쌉니다.
그리고 해당 경로에 마운트합니다.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | 참고
이전에 `fastapi.middleware.wsgi``WSGIMiddleware` 사용을 권장했지만 이제는 더 이상 권장되지 않습니다.
대신 `a2wsgi` 패키지 사용을 권장합니다. 사용 방법은 동일합니다.
단, `a2wsgi` 패키지가 설치되어 있고 `a2wsgi`에서 `WSGIMiddleware`를 올바르게 import 하는지만 확인하세요.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## 확인하기 { #check-it }
이제 `/v1/` 경로에 있는 모든 요청은 Flask 애플리케이션에서 처리됩니다.
이제 `/v1/` 경로에 있는 모든 요청은 Flask 응용 프로그램에서 처리됩니다.
그리고 나머지는 **FastAPI**에 의해 처리됩니다.
실행하 <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>로 이동하면 Flask의 응답을 볼 수 있습니다:
실행하 <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>로 이동해서 Flask의 응답을 볼 수 있습니다:
```txt
Hello, World from Flask!
```
그리고 <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a>로 이동하면 **FastAPI**의 응답을 볼 수 있습니다:
그리고 다음으로 이동하면 <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a> **FastAPI**의 응답을 볼 수 있습니다:
```JSON
{

View File

@@ -145,6 +145,8 @@ Successfully installed fastapi pydantic
* 다음 내용으로 `main.py` 파일을 만듭니다:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -156,7 +158,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -243,14 +245,14 @@ Docker 지시어 <a href="https://docs.docker.com/reference/dockerfile/#cmd" cla
✅ **Exec** form:
```Dockerfile
# ✅ 이렇게 하세요
# ✅ Do this
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
```
⛔️ **Shell** form:
```Dockerfile
# ⛔️ 이렇게 하지 마세요
# ⛔️ Don't do this
CMD fastapi run app/main.py --port 80
```
@@ -454,7 +456,7 @@ Traefik은 Docker, Kubernetes 등과 통합되어 있어, 이를 사용해 컨
## 복제 - 프로세스 개수 { #replication-number-of-processes }
**Kubernetes**, Docker Swarm Mode, Nomad 등의 복잡한 시스템으로 여러 머신에 분산된 컨테이너를 관리하는 <abbr title="어떤 방식으로 연결되어 함께 동작하도록 구성된 머신의 그룹">클러스터</abbr>를 사용한다면, 각 컨테이너에서(**워커를 사용하는 Uvicorn** 같은) **프로세스 매니저**를 쓰는 대신, **클러스터 레벨**에서 **복제를 처리**하고 싶을 가능성이 큽니다.
**Kubernetes**, Docker Swarm Mode, Nomad 등의 복잡한 시스템으로 여러 머신에 분산된 컨테이너를 관리하는 <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr>를 사용한다면, 각 컨테이너에서(**워커를 사용하는 Uvicorn** 같은) **프로세스 매니저**를 쓰는 대신, **클러스터 레벨**에서 **복제를 처리**하고 싶을 가능성이 큽니다.
Kubernetes 같은 분산 컨테이너 관리 시스템은 보통 들어오는 요청에 대한 **로드 밸런싱**을 지원하면서도, **컨테이너 복제**를 처리하는 통합된 방법을 가지고 있습니다. 모두 **클러스터 레벨**에서요.
@@ -578,7 +580,7 @@ Kubernetes를 사용한다면, 이는 아마도 <a href="https://kubernetes.io/d
그리고 여러 워커가 필요하다면, `--workers` 커맨드 라인 옵션을 간단히 사용하면 됩니다.
/// note | 기술 세부사항
/// note Technical Details | 기술 세부사항
이 Docker 이미지는 Uvicorn이 죽은 워커를 관리하고 재시작하는 기능을 지원하지 않던 시기에 만들어졌습니다. 그래서 Gunicorn과 Uvicorn을 함께 사용해야 했고, Gunicorn이 Uvicorn 워커 프로세스를 관리하고 재시작하도록 하기 위해 상당한 복잡성이 추가되었습니다.

View File

@@ -40,7 +40,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
* **빠름**: (Starlette과 Pydantic 덕분에) **NodeJS** 및 **Go**와 대등할 정도로 매우 높은 성능. [사용 가능한 가장 빠른 파이썬 프레임워크 중 하나](#performance).
* **빠른 코드 작성**: 약 200%에서 300%까지 기능 개발 속도 증가. *
* **적은 버그**: 사람(개발자)에 의한 에러 약 40% 감소. *
* **직관적**: 훌륭한 편집기 지원. 모든 곳에서 <abbr title="다른 말로는: auto-complete, autocompletion, IntelliSense">자동완성</abbr>. 적은 디버깅 시간.
* **직관적**: 훌륭한 편집기 지원. 모든 곳에서 <abbr title="also known as auto-complete, autocompletion, IntelliSense">자동완성</abbr>. 적은 디버깅 시간.
* **쉬움**: 쉽게 사용하고 배우도록 설계. 적은 문서 읽기 시간.
* **짧음**: 코드 중복 최소화. 각 매개변수 선언의 여러 기능. 적은 버그.
* **견고함**: 준비된 프로덕션 용 코드를 얻으십시오. 자동 대화형 문서와 함께.
@@ -127,7 +127,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
웹 API 대신 터미널에서 사용할 <abbr title="Command Line Interface - 커맨드 라인 인터페이스">CLI</abbr> 앱을 만들고 있다면, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>를 확인해 보십시오.
웹 API 대신 터미널에서 사용할 <abbr title="Command Line Interface">CLI</abbr> 앱을 만들고 있다면, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>를 확인해 보십시오.
**Typer**는 FastAPI의 동생입니다. 그리고 **CLI를 위한 FastAPI**가 되기 위해 생겼습니다. ⌨️ 🚀
@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
다음 내용으로 `main.py` 파일을 만드십시오:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
여러분의 코드가 `async` / `await`을 사용한다면, `async def`를 사용하십시오:
```Python hl_lines="7 12"
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -284,7 +288,9 @@ INFO: Application startup complete.
Pydantic 덕분에 표준 Python 타입을 사용해 본문을 선언합니다.
```Python hl_lines="2 7-10 23-25"
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool | None = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@@ -368,7 +374,7 @@ item: Item
* 데이터 검증:
* 데이터가 유효하지 않을 때 자동으로 생성하는 명확한 에러.
* 깊이 중첩된 JSON 객체에 대한 유효성 검사.
* 입력 데이터 <abbr title="다른 말로는: serialization, parsing, marshalling">변환</abbr>: 네트워크에서 파이썬 데이터 및 타입으로 전송. 읽을 수 있는 것들:
* 입력 데이터 <abbr title="also known as: serialization, parsing, marshalling">변환</abbr>: 네트워크에서 파이썬 데이터 및 타입으로 전송. 읽을 수 있는 것들:
* JSON.
* 경로 매개변수.
* 쿼리 매개변수.
@@ -376,7 +382,7 @@ item: Item
* 헤더.
* 폼(Forms).
* 파일.
* 출력 데이터 <abbr title="다른 말로는: serialization, parsing, marshalling">변환</abbr>: 파이썬 데이터 및 타입을 네트워크 데이터로 전환(JSON 형식으로):
* 출력 데이터 <abbr title="also known as: serialization, parsing, marshalling">변환</abbr>: 파이썬 데이터 및 타입을 네트워크 데이터로 전환(JSON 형식으로):
* 파이썬 타입 변환 (`str`, `int`, `float`, `bool`, `list`, 등).
* `datetime` 객체.
* `UUID` 객체.
@@ -439,7 +445,7 @@ item: Item
* 서로 다른 장소에서 **매개변수** 선언: **헤더**, **쿠키**, **폼 필드** 그리고 **파일**.
* `maximum_length` 또는 `regex`처럼 **유효성 제약**하는 방법.
* 강력하고 사용하기 쉬운 **<abbr title="다른 말로는: components, resources, providers, services, injectables">의존성 주입</abbr>** 시스템.
* 강력하고 사용하기 쉬운 **<abbr title="also known as components, resources, providers, services, injectables">의존성 주입</abbr>** 시스템.
* **OAuth2** 지원을 포함한 **JWT tokens** 및 **HTTP Basic**을 갖는 보안과 인증.
* (Pydantic 덕분에) **깊은 중첩 JSON 모델**을 선언하는데 더 진보한 (하지만 마찬가지로 쉬운) 기술.
* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> 및 기타 라이브러리와의 **GraphQL** 통합.

View File

@@ -102,16 +102,15 @@
기본적으로 단일 값은 쿼리 매개변수로 해석되므로, 명시적으로 `Query`를 추가할 필요 없이 이렇게 하면 됩니다:
```Python
q: str | None = None
```
또는 Python 3.9에서는:
```Python
q: Union[str, None] = None
```
또는 Python 3.10 이상에서는:
```Python
q: str | None = None
```
예를 들어:

View File

@@ -52,11 +52,11 @@
`summary``description`을 추가할 수 있습니다:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## 독스트링으로 만든 설명 { #description-from-docstring }
설명은 보통 길어지고 여러 줄에 걸쳐있기 때문에, *경로 처리* 설명을 함수 <abbr title="문서화에 사용되는 함수 내부 첫 표현식의 여러 줄 문자열(어떤 변수에도 할당되지 않음)">docstring</abbr>에 선언할 수 있으며, **FastAPI**는 그곳에서 이를 읽습니다.
설명은 보통 길어지고 여러 줄에 걸쳐있기 때문에, *경로 처리* 설명을 함수 <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation 문서화에 사용되는 함수 내부 첫 표현식의 여러 줄 문자열(어떤 변수에도 할당되지 않음)">docstring</abbr>에 선언할 수 있으며, **FastAPI**는 그곳에서 이를 읽습니다.
독스트링에는 <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>을 작성할 수 있으며, (독스트링의 들여쓰기를 고려하여) 올바르게 해석되고 표시됩니다.
@@ -70,7 +70,7 @@
`response_description` 매개변수로 응답에 관한 설명을 명시할 수 있습니다:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info | 정보
@@ -90,7 +90,7 @@ OpenAPI는 각 *경로 처리*가 응답에 관한 설명을 요구할 것을
## *경로 처리* 지원중단하기 { #deprecate-a-path-operation }
*경로 처리*를 제거하지 않고 <abbr title="구식이며 사용하지 않는 것이 권장됨">deprecated</abbr>로 표시해야 한다면, `deprecated` 매개변수를 전달하면 됩니다:
*경로 처리*를 제거하지 않고 <abbr title="obsolete, recommended not to use it 구식이며 사용하지 않는 것이 권장됨">deprecated</abbr>로 표시해야 한다면, `deprecated` 매개변수를 전달하면 됩니다:
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}

View File

@@ -148,7 +148,7 @@ Antes do FastAPI 0.106.0, lançar exceções após o `yield` não era possível,
Isso foi projetado assim principalmente para permitir o uso dos mesmos objetos "yielded" por dependências dentro de tarefas em segundo plano, porque o código de saída seria executado depois que as tarefas em segundo plano fossem concluídas.
Isso foi alterado no FastAPI 0.106.0 com a intenção de não manter recursos enquanto se espera a response percorrer a rede.
Isso foi alterado no FastAPI 0.106.0 com a intenção de não manter recursos enquanto se espera a resposta percorrer a rede.
/// tip | Dica

View File

@@ -6,29 +6,13 @@ Para isso, você pode utilizar o `WSGIMiddleware` para encapsular a sua aplicaç
## Usando `WSGIMiddleware` { #using-wsgimiddleware }
/// info | Informação
Isso requer instalar `a2wsgi`, por exemplo com `pip install a2wsgi`.
///
Você precisa importar o `WSGIMiddleware` de `a2wsgi`.
Você precisa importar o `WSGIMiddleware`.
Em seguida, encapsule a aplicação WSGI (e.g. Flask) com o middleware.
E então monte isso sob um path.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | Nota
Anteriormente, recomendava-se usar `WSGIMiddleware` de `fastapi.middleware.wsgi`, mas agora está descontinuado.
É aconselhável usar o pacote `a2wsgi` em seu lugar. O uso permanece o mesmo.
Apenas certifique-se de que o pacote `a2wsgi` está instalado e importe `WSGIMiddleware` corretamente de `a2wsgi`.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Confira { #check-it }

View File

@@ -145,6 +145,8 @@ Há outros formatos e ferramentas para definir e instalar dependências de pacot
* Crie um arquivo `main.py` com:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -156,7 +158,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -570,7 +572,7 @@ Se você tiver uma configuração simples, com um **único contêiner** que ent
### Imagem Docker base { #base-docker-image }
Antes havia uma imagem oficial do FastAPI para Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi-docker</a>. Mas agora ela está descontinuada. ⛔️
Antes havia uma imagem oficial do FastAPI para Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Mas agora ela está descontinuada. ⛔️
Você provavelmente **não** deve usar essa imagem base do Docker (ou qualquer outra semelhante).

View File

@@ -33,7 +33,7 @@
---
FastAPI é um moderno e rápido (alta performance) framework web para construção de APIs com Python, baseado nos type hints padrões do Python.
FastAPI é um moderno e rápido (alta performance) _framework web_ para construção de APIs com Python, baseado nos _type hints_ padrões do Python.
Os recursos chave são:
@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
Crie um arquivo `main.py` com:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
Se seu código utiliza `async` / `await`, use `async def`:
```Python hl_lines="7 12"
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -284,7 +288,9 @@ Agora modifique o arquivo `main.py` para receber um corpo de uma requisição `P
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
```Python hl_lines="2 7-10 23-25"
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool | None = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@@ -405,7 +411,7 @@ Voltando ao código do exemplo anterior, **FastAPI** irá:
* Documentar tudo com OpenAPI, que poderá ser usado por:
* Sistemas de documentação interativos.
* Sistemas de clientes de geração de código automáticos, para muitas linguagens.
* Fornecer diretamente 2 interfaces web de documentação interativa.
* Fornecer diretamente 2 interfaces _web_ de documentação interativa.
---
@@ -504,7 +510,7 @@ Siga os tutoriais do seu provedor de nuvem para implantar aplicações FastAPI c
## Performance { #performance }
Testes de performance da Independent TechEmpower mostram aplicações **FastAPI** rodando sob Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos frameworks Python mais rápidos disponíveis</a>, somente atrás de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*)
Testes de performance da _Independent TechEmpower_ mostram aplicações **FastAPI** rodando sob Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos _frameworks_ Python mais rápidos disponíveis</a>, somente atrás de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*)
Para entender mais sobre isso, veja a seção <a href="https://fastapi.tiangolo.com/pt/benchmarks/" class="internal-link" target="_blank">Comparações</a>.
@@ -524,7 +530,7 @@ Utilizado pelo Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Obrigatório caso você queira utilizar o `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obrigatório se você quer utilizar a configuração padrão de templates.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <abbr title="convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</abbr> de formulário, com `request.form()`.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <abbr title="converting the string that comes from an HTTP request into Python data - convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</abbr> de formulário, com `request.form()`.
Utilizado pelo FastAPI:

View File

@@ -101,13 +101,13 @@ Obviamente, você também pode declarar parâmetros de consulta assim que você
Dado que, por padrão, valores singulares são interpretados como parâmetros de consulta, você não precisa explicitamente adicionar uma `Query`, você pode somente:
```Python
q: str | None = None
q: Union[str, None] = None
```
Ou em Python 3.9:
Ou como em Python 3.10 e versões superiores:
```Python
q: Union[str, None] = None
q: str | None = None
```
Por exemplo:

View File

@@ -52,7 +52,7 @@ Nestes casos, pode fazer sentido armazenar as tags em um `Enum`.
Você pode adicionar um `summary` e uma `description`:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## Descrição do docstring { #description-from-docstring }
@@ -70,7 +70,7 @@ Ela será usada nas documentações interativas:
Você pode especificar a descrição da resposta com o parâmetro `response_description`:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info | Informação

View File

@@ -48,7 +48,7 @@
checker(q="somequery")
```
…и передаст возвращённое значение как значение зависимости в нашу *функцию-обработчике пути* в параметр `fixed_content_included`:
…и передаст возвращённое значение как значение зависимости в параметр `fixed_content_included` нашей *функции-обработчика пути*:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}

View File

@@ -6,13 +6,29 @@
## Использование `WSGIMiddleware` { #using-wsgimiddleware }
Нужно импортировать `WSGIMiddleware`.
/// info | Информация
Для этого требуется установить `a2wsgi`, например с помощью `pip install a2wsgi`.
///
Нужно импортировать `WSGIMiddleware` из `a2wsgi`.
Затем оберните WSGIприложение (например, Flask) в middleware (Промежуточный слой).
После этого смонтируйте его на путь.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | Примечание
Ранее рекомендовалось использовать `WSGIMiddleware` из `fastapi.middleware.wsgi`, но теперь он помечен как устаревший.
Вместо него рекомендуется использовать пакет `a2wsgi`. Использование остаётся таким же.
Просто убедитесь, что пакет `a2wsgi` установлен, и импортируйте `WSGIMiddleware` из `a2wsgi`.
///
## Проверьте { #check-it }

View File

@@ -145,8 +145,6 @@ Successfully installed fastapi pydantic
* Создайте файл `main.py` со следующим содержимым:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -158,7 +156,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```

View File

@@ -161,8 +161,6 @@ $ pip install "fastapi[standard]"
Создайте файл `main.py` со следующим содержимым:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -174,7 +172,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None):
Если ваш код использует `async` / `await`, используйте `async def`:
```Python hl_lines="9 14"
from typing import Union
```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@@ -197,7 +193,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
async def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@@ -288,9 +284,7 @@ INFO: Application startup complete.
Объявите тело запроса, используя стандартные типы Python, спасибо Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
@@ -300,7 +294,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
is_offer: bool | None = None
@app.get("/")
@@ -309,7 +303,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}

View File

@@ -101,13 +101,13 @@
Поскольку по умолчанию, отдельные значения интерпретируются как query-параметры, вам не нужно явно добавлять `Query`, вы можете просто сделать так:
```Python
q: Union[str, None] = None
q: str | None = None
```
Или в Python 3.10 и выше:
Или в Python 3.9:
```Python
q: str | None = None
q: Union[str, None] = None
```
Например:
@@ -116,7 +116,7 @@ q: str | None = None
/// info | Информация
`Body` также имеет все те же дополнительные параметры валидации и метаданных, как у `Query`,`Path` и других, которые вы увидите позже.
`Body` также имеет все те же дополнительные параметры валидации и метаданных, как у `Query`, `Path` и других, которые вы увидите позже.
///

View File

@@ -52,7 +52,7 @@
Вы можете добавить параметры `summary` и `description`:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
## Описание из строк документации { #description-from-docstring }
@@ -70,7 +70,7 @@
Вы можете указать описание ответа с помощью параметра `response_description`:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info | Дополнительная информация
@@ -78,7 +78,7 @@
///
/// check
/// check | Проверка
OpenAPI указывает, что каждой *операции пути* необходимо описание ответа.

View File

@@ -1,34 +1,18 @@
# WSGI'yi Dahil Etme - Flask, Django ve Diğerleri { #including-wsgi-flask-django-others }
WSGI uygulamalarını [Alt Uygulamalar - Mount Etme](sub-applications.md){.internal-link target=_blank}, [Bir Proxy Arkasında](behind-a-proxy.md){.internal-link target=_blank} bölümlerinde gördüğünüz gibi mount edebilirsiniz.
WSGI uygulamalarını [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bölümlerinde gördüğünüz gibi mount edebilirsiniz.
Bunun için `WSGIMiddleware`'ı kullanabilir ve bunu WSGI uygulamanızı (örneğin Flask, Django vb.) sarmalamak için kullanabilirsiniz.
## `WSGIMiddleware` Kullanımı { #using-wsgimiddleware }
/// info | Bilgi
Bunun için `a2wsgi` kurulmalıdır; örneğin `pip install a2wsgi` ile.
///
`WSGIMiddleware`'ı `a2wsgi` paketinden import etmeniz gerekir.
`WSGIMiddleware`'ı import etmeniz gerekir.
Ardından WSGI (örn. Flask) uygulamasını middleware ile sarmalayın.
Ve sonra bunu bir path'in altına mount edin.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note | Not
Önceden, `fastapi.middleware.wsgi` içindeki `WSGIMiddleware`'ın kullanılması öneriliyordu, ancak artık kullanımdan kaldırıldı.
Bunun yerine `a2wsgi` paketini kullanmanız önerilir. Kullanım aynıdır.
Sadece `a2wsgi` paketinin kurulu olduğundan emin olun ve `WSGIMiddleware`'ı `a2wsgi` içinden doğru şekilde import edin.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Kontrol Edelim { #check-it }

View File

@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
Şu içerikle `main.py` adında bir dosya oluşturalım:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
Eğer kodunuz `async` / `await` kullanıyorsa, `async def` kullanın:
```Python hl_lines="7 12"
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
@@ -284,7 +288,9 @@ Alternatif otomatik dokümantasyonu göreceksiniz (<a href="https://github.com/R
Body'yi Pydantic sayesinde standart Python tiplerini kullanarak tanımlayalım.
```Python hl_lines="2 7-10 23-25"
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool | None = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.128.2"
__version__ = "0.128.1"
from starlette import status as status

View File

@@ -51,7 +51,7 @@ from fastapi.logger import logger
from fastapi.security.oauth2 import SecurityScopes
from fastapi.types import DependencyCacheKey
from fastapi.utils import create_model_field, get_path_param_names
from pydantic import BaseModel, Json
from pydantic import BaseModel
from pydantic.fields import FieldInfo
from starlette.background import BackgroundTasks as StarletteBackgroundTasks
from starlette.concurrency import run_in_threadpool
@@ -66,7 +66,6 @@ from starlette.requests import HTTPConnection, Request
from starlette.responses import Response
from starlette.websockets import WebSocket
from typing_extensions import Literal, get_args, get_origin
from typing_inspection.typing_objects import is_typealiastype
multipart_not_installed_error = (
'Form data requires "python-multipart" to be installed. \n'
@@ -371,9 +370,6 @@ def analyze_param(
depends = None
type_annotation: Any = Any
use_annotation: Any = Any
if is_typealiastype(annotation):
# unpack in case PEP 695 type syntax is used
annotation = annotation.__value__
if annotation is not inspect.Signature.empty:
use_annotation = annotation
type_annotation = annotation
@@ -453,9 +449,7 @@ def analyze_param(
depends = dataclasses.replace(depends, dependency=type_annotation)
# Handle non-param type annotations like Request
# Only apply special handling when there's no explicit Depends - if there's a Depends,
# the dependency will be called and its return value used instead of the special injection
if depends is None and lenient_issubclass(
if lenient_issubclass(
type_annotation,
(
Request,
@@ -466,6 +460,7 @@ def analyze_param(
SecurityScopes,
),
):
assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}"
assert field_info is None, (
f"Cannot specify FastAPI annotation for type {type_annotation!r}"
)
@@ -726,19 +721,11 @@ def _validate_value_with_model_field(
return v_, []
def _is_json_field(field: ModelField) -> bool:
return any(type(item) is Json for item in field.field_info.metadata)
def _get_multidict_value(
field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None
) -> Any:
alias = alias or get_validation_alias(field)
if (
(not _is_json_field(field))
and is_sequence_field(field)
and isinstance(values, (ImmutableMultiDict, Headers))
):
if is_sequence_field(field) and isinstance(values, (ImmutableMultiDict, Headers)):
value = values.getlist(alias)
else:
value = values.get(alias, None)

View File

@@ -46,7 +46,6 @@ dependencies = [
"starlette>=0.40.0,<0.51.0",
"pydantic>=2.7.0",
"typing-extensions>=4.8.0",
"typing-inspection>=0.4.2",
"annotated-doc>=0.0.2",
]

View File

@@ -23,7 +23,7 @@ SUPPORTED_LANGS = {
"de",
"en",
"es",
"fr",
# "fr",
"ja",
"ko",
"pt",
@@ -31,7 +31,7 @@ SUPPORTED_LANGS = {
"tr",
"uk",
# "zh",
"zh-hant",
# "zh-hant",
}

View File

@@ -347,12 +347,9 @@ def list_outdated(language: str) -> list[Path]:
@app.command()
def update_outdated(
language: Annotated[str, typer.Option(envvar="LANGUAGE")],
max: Annotated[int, typer.Option(envvar="MAX")] = 10,
) -> None:
def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None:
outdated_paths = list_outdated(language)
for path in outdated_paths[:max]:
for path in outdated_paths:
print(f"Updating lang: {language} path: {path}")
translate_page(language=language, en_path=path)
print(f"Done updating: {path}")
@@ -360,12 +357,9 @@ def update_outdated(
@app.command()
def add_missing(
language: Annotated[str, typer.Option(envvar="LANGUAGE")],
max: Annotated[int, typer.Option(envvar="MAX")] = 10,
) -> None:
def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None:
missing_paths = list_missing(language)
for path in missing_paths[:max]:
for path in missing_paths:
print(f"Adding lang: {language} path: {path}")
translate_page(language=language, en_path=path)
print(f"Done adding: {path}")
@@ -373,14 +367,11 @@ def add_missing(
@app.command()
def update_and_add(
language: Annotated[str, typer.Option(envvar="LANGUAGE")],
max: Annotated[int, typer.Option(envvar="MAX")] = 10,
) -> None:
def update_and_add(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None:
print(f"Updating outdated translations for {language}")
update_outdated(language=language, max=max)
update_outdated(language=language)
print(f"Adding missing translations for {language}")
add_missing(language=language, max=max)
add_missing(language=language)
print(f"Done updating and adding for {language}")

View File

@@ -1,27 +0,0 @@
from typing import Annotated
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from typing_extensions import TypeAliasType
async def some_value() -> int:
return 123
DependedValue = TypeAliasType(
"DependedValue", Annotated[int, Depends(some_value)], type_params=()
)
def test_pep695_type_dependencies():
app = FastAPI()
@app.get("/")
async def get_with_dep(value: DependedValue) -> str: # noqa
return f"value: {value}"
client = TestClient(app)
response = client.get("/")
assert response.status_code == 200
assert response.text == '"value: 123"'

View File

@@ -1,63 +0,0 @@
import json
from typing import Annotated
from fastapi import Cookie, FastAPI, Form, Header, Query
from fastapi.testclient import TestClient
from pydantic import Json
app = FastAPI()
@app.post("/form-json-list")
def form_json_list(items: Annotated[Json[list[str]], Form()]) -> list[str]:
return items
@app.get("/query-json-list")
def query_json_list(items: Annotated[Json[list[str]], Query()]) -> list[str]:
return items
@app.get("/header-json-list")
def header_json_list(x_items: Annotated[Json[list[str]], Header()]) -> list[str]:
return x_items
@app.get("/cookie-json-list")
def cookie_json_list(items: Annotated[Json[list[str]], Cookie()]) -> list[str]:
return items
client = TestClient(app)
def test_form_json_list():
response = client.post(
"/form-json-list", data={"items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_query_json_list():
response = client.get(
"/query-json-list", params={"items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_header_json_list():
response = client.get(
"/header-json-list", headers={"x-items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_cookie_json_list():
client.cookies.set("items", json.dumps(["abc", "def"]))
response = client.get("/cookie-json-list")
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
client.cookies.clear()

View File

@@ -1,173 +0,0 @@
"""Test using special types (Response, Request, BackgroundTasks) as dependency annotations.
These tests verify that special FastAPI types can be used with Depends() annotations
and that the dependency injection system properly handles them.
"""
from typing import Annotated
from fastapi import BackgroundTasks, Depends, FastAPI, Request, Response
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
def test_response_with_depends_annotated():
"""Response type hint should work with Annotated[Response, Depends(...)]."""
app = FastAPI()
def modify_response(response: Response) -> Response:
response.headers["X-Custom"] = "modified"
return response
@app.get("/")
def endpoint(response: Annotated[Response, Depends(modify_response)]):
return {"status": "ok"}
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert resp.json() == {"status": "ok"}
assert resp.headers.get("X-Custom") == "modified"
def test_response_with_depends_default():
"""Response type hint should work with Response = Depends(...)."""
app = FastAPI()
def modify_response(response: Response) -> Response:
response.headers["X-Custom"] = "modified"
return response
@app.get("/")
def endpoint(response: Response = Depends(modify_response)):
return {"status": "ok"}
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert resp.json() == {"status": "ok"}
assert resp.headers.get("X-Custom") == "modified"
def test_response_without_depends():
"""Regular Response injection should still work."""
app = FastAPI()
@app.get("/")
def endpoint(response: Response):
response.headers["X-Direct"] = "set"
return {"status": "ok"}
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert resp.json() == {"status": "ok"}
assert resp.headers.get("X-Direct") == "set"
def test_response_dependency_chain():
"""Response dependency should work in a chain of dependencies."""
app = FastAPI()
def first_modifier(response: Response) -> Response:
response.headers["X-First"] = "1"
return response
def second_modifier(
response: Annotated[Response, Depends(first_modifier)],
) -> Response:
response.headers["X-Second"] = "2"
return response
@app.get("/")
def endpoint(response: Annotated[Response, Depends(second_modifier)]):
return {"status": "ok"}
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert resp.headers.get("X-First") == "1"
assert resp.headers.get("X-Second") == "2"
def test_response_dependency_returns_different_response_instance():
"""Dependency that returns a different Response instance should work.
When a dependency returns a new Response object (e.g., JSONResponse) instead
of modifying the injected one, the returned response should be used and any
modifications to it in the endpoint should be preserved.
"""
app = FastAPI()
def default_response() -> Response:
response = JSONResponse(content={"status": "ok"})
response.headers["X-Custom"] = "initial"
return response
@app.get("/")
def endpoint(response: Annotated[Response, Depends(default_response)]):
response.headers["X-Custom"] = "modified"
return response
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert resp.json() == {"status": "ok"}
assert resp.headers.get("X-Custom") == "modified"
# Tests for Request type hint with Depends
def test_request_with_depends_annotated():
"""Request type hint should work in dependency chain."""
app = FastAPI()
def extract_request_info(request: Request) -> dict:
return {
"path": request.url.path,
"user_agent": request.headers.get("user-agent", "unknown"),
}
@app.get("/")
def endpoint(
info: Annotated[dict, Depends(extract_request_info)],
):
return info
client = TestClient(app)
resp = client.get("/", headers={"user-agent": "test-agent"})
assert resp.status_code == 200
assert resp.json() == {"path": "/", "user_agent": "test-agent"}
# Tests for BackgroundTasks type hint with Depends
def test_background_tasks_with_depends_annotated():
"""BackgroundTasks type hint should work with Annotated[BackgroundTasks, Depends(...)]."""
app = FastAPI()
task_results = []
def background_task(message: str):
task_results.append(message)
def add_background_task(background_tasks: BackgroundTasks) -> BackgroundTasks:
background_tasks.add_task(background_task, "from dependency")
return background_tasks
@app.get("/")
def endpoint(
background_tasks: Annotated[BackgroundTasks, Depends(add_background_task)],
):
background_tasks.add_task(background_task, "from endpoint")
return {"status": "ok"}
client = TestClient(app)
resp = client.get("/")
assert resp.status_code == 200
assert "from dependency" in task_results
assert "from endpoint" in task_results

2
uv.lock generated
View File

@@ -1021,7 +1021,6 @@ dependencies = [
{ name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
[package.optional-dependencies]
@@ -1203,7 +1202,6 @@ requires-dist = [
{ name = "pyyaml", marker = "extra == 'all'", specifier = ">=5.3.1" },
{ name = "starlette", specifier = ">=0.40.0,<0.51.0" },
{ name = "typing-extensions", specifier = ">=4.8.0" },
{ name = "typing-inspection", specifier = ">=0.4.2" },
{ name = "ujson", marker = "extra == 'all'", specifier = ">=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0" },
{ name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.12.0" },
{ name = "uvicorn", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.12.0" },