-# Réponses supplémentaires dans OpenAPI
+# Réponses supplémentaires dans OpenAPI { #additional-responses-in-openapi }
-/// warning | Attention
+/// warning | Alertes
Ceci concerne un sujet plutÎt avancé.
Mais pour ces réponses supplémentaires, vous devez vous assurer de renvoyer directement une `Response` comme `JSONResponse`, avec votre code HTTP et votre contenu.
-## Réponse supplémentaire avec `model`
+## Réponse supplémentaire avec `model` { #additional-response-with-model }
-Vous pouvez ajouter à votre décorateur de *paramÚtre de chemin* un paramÚtre `responses`.
+Vous pouvez passer à vos décorateurs de *chemin d'accÚs* un paramÚtre `responses`.
Il prend comme valeur un `dict` dont les clés sont des codes HTTP pour chaque réponse, comme `200`, et la valeur de ces clés sont d'autres `dict` avec des informations pour chacun d'eux.
Par exemple, pour déclarer une autre réponse avec un code HTTP `404` et un modÚle Pydantic `Message`, vous pouvez écrire :
-{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
+{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
/// note | Remarque
///
-Les réponses générées au format OpenAPI pour cette *opération de chemin* seront :
+Les réponses générées au format OpenAPI pour ce *chemin d'accÚs* seront :
```JSON hl_lines="3-12"
{
}
```
-## Types de médias supplémentaires pour la réponse principale
+## Types de médias supplémentaires pour la réponse principale { #additional-media-types-for-the-main-response }
Vous pouvez utiliser ce mĂȘme paramĂštre `responses` pour ajouter diffĂ©rents types de mĂ©dias pour la mĂȘme rĂ©ponse principale.
-Par exemple, vous pouvez ajouter un type de média supplémentaire `image/png`, en déclarant que votre *opération de chemin* peut renvoyer un objet JSON (avec le type de média `application/json`) ou une image PNG :
+Par exemple, vous pouvez ajouter un type de média supplémentaire `image/png`, en déclarant que votre *chemin d'accÚs* peut renvoyer un objet JSON (avec le type de média `application/json`) ou une image PNG :
-{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
+{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *}
/// note | Remarque
///
-## Combinaison d'informations
+## Combiner les informations { #combining-information }
Vous pouvez également combiner des informations de réponse provenant de plusieurs endroits, y compris les paramÚtres `response_model`, `status_code` et `responses`.
Et une réponse avec un code HTTP `200` qui utilise votre `response_model`, mais inclut un `example` personnalisé :
-{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
+{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
Tout sera combiné et inclus dans votre OpenAPI, et affiché dans la documentation de l'API :
<img src="/img/tutorial/additional-responses/image01.png">
-## Combinez les réponses prédéfinies et les réponses personnalisées
+## Combinez les réponses prédéfinies et les réponses personnalisées { #combine-predefined-responses-and-custom-ones }
-Vous voulez peut-ĂȘtre avoir des rĂ©ponses prĂ©dĂ©finies qui s'appliquent Ă de nombreux *paramĂštre de chemin*, mais vous souhaitez les combiner avec des rĂ©ponses personnalisĂ©es nĂ©cessaires Ă chaque *opĂ©ration de chemin*.
+Vous voulez peut-ĂȘtre avoir des rĂ©ponses prĂ©dĂ©finies qui s'appliquent Ă de nombreux *chemins d'accĂšs*, mais vous souhaitez les combiner avec des rĂ©ponses personnalisĂ©es nĂ©cessaires Ă chaque *chemin d'accĂšs*.
-Dans ces cas, vous pouvez utiliser la technique Python "d'affection par décomposition" (appelé _unpacking_ en anglais) d'un `dict` avec `**dict_to_unpack` :
+Dans ces cas, vous pouvez utiliser la technique Python « unpacking » d'un `dict` avec `**dict_to_unpack` :
```Python
old_dict = {
}
```
-Vous pouvez utiliser cette technique pour réutiliser certaines réponses prédéfinies dans vos *paramÚtres de chemin* et les combiner avec des réponses personnalisées supplémentaires.
+Vous pouvez utiliser cette technique pour réutiliser certaines réponses prédéfinies dans vos *chemins d'accÚs* et les combiner avec des réponses personnalisées supplémentaires.
Par exemple:
-{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
+{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *}
-## Plus d'informations sur les réponses OpenAPI
+## Plus d'informations sur les réponses OpenAPI { #more-information-about-openapi-responses }
Pour voir exactement ce que vous pouvez inclure dans les réponses, vous pouvez consulter ces sections dans la spécification OpenAPI :
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responsesObject" class="external-link" target="_blank">Objet Responses de OpenAPI </a>, il inclut le `Response Object`.
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responseObject" class="external-link" target="_blank">Objet Response de OpenAPI </a>, vous pouvez inclure n'importe quoi directement dans chaque réponse à l'intérieur de votre paramÚtre `responses`. Y compris `description`, `headers`, `content` (à l'intérieur de cela, vous déclarez différents types de médias et schémas JSON) et `links`.
+* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Objet Responses de OpenAPI</a>, il inclut le `Response Object`.
+* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Objet Response de OpenAPI</a>, vous pouvez inclure n'importe quoi directement dans chaque réponse à l'intérieur de votre paramÚtre `responses`. Y compris `description`, `headers`, `content` (à l'intérieur de cela, vous déclarez différents types de médias et schémas JSON) et `links`.
-# Codes HTTP supplémentaires
+# Codes HTTP supplémentaires { #additional-status-codes }
Par défaut, **FastAPI** renverra les réponses à l'aide d'une structure de données `JSONResponse`, en plaçant la réponse de votre *chemin d'accÚs* à l'intérieur de cette `JSONResponse`.
Il utilisera le code HTTP par défaut ou celui que vous avez défini dans votre *chemin d'accÚs*.
-## Codes HTTP supplémentaires
+## Codes HTTP supplémentaires { #additional-status-codes_1 }
Si vous souhaitez renvoyer des codes HTTP supplémentaires en plus du code principal, vous pouvez le faire en renvoyant directement une `Response`, comme une `JSONResponse`, et en définissant directement le code HTTP supplémentaire.
-Par exemple, disons que vous voulez avoir un *chemin d'accÚs* qui permet de mettre à jour les éléments et renvoie les codes HTTP 200 "OK" en cas de succÚs.
+Par exemple, disons que vous voulez avoir un *chemin d'accÚs* qui permet de mettre à jour les éléments et renvoie les codes HTTP 200 « OK » en cas de succÚs.
-Mais vous voulez aussi qu'il accepte de nouveaux éléments. Et lorsque les éléments n'existaient pas auparavant, il les crée et renvoie un code HTTP de 201 "Créé".
+Mais vous voulez aussi qu'il accepte de nouveaux éléments. Et lorsque les éléments n'existaient pas auparavant, il les crée et renvoie un code HTTP de 201 « Créé ».
Pour y parvenir, importez `JSONResponse` et renvoyez-y directement votre contenu, en définissant le `status_code` que vous souhaitez :
-{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *}
+{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
-/// warning | Attention
+/// warning | Alertes
Lorsque vous renvoyez une `Response` directement, comme dans l'exemple ci-dessus, elle sera renvoyée directement.
Elle ne sera pas sérialisée avec un modÚle.
-Assurez-vous qu'il contient les données souhaitées et que les valeurs soient dans un format JSON valides (si vous utilisez une `JSONResponse`).
+Assurez-vous qu'il contient les données souhaitées et que les valeurs sont dans un format JSON valide (si vous utilisez une `JSONResponse`).
///
Vous pouvez également utiliser `from starlette.responses import JSONResponse`.
-Pour plus de commoditĂ©s, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des rĂ©ponses disponibles proviennent directement de Starlette. Il en est de mĂȘme avec l'objet `statut`.
+Pour plus de commoditĂ©s, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des rĂ©ponses disponibles proviennent directement de Starlette. Il en est de mĂȘme avec `status`.
///
-##Â Documents OpenAPI et API
+## Documents OpenAPI et API { #openapi-and-api-docs }
Si vous renvoyez directement des codes HTTP et des réponses supplémentaires, ils ne seront pas inclus dans le schéma OpenAPI (la documentation de l'API), car FastAPI n'a aucun moyen de savoir à l'avance ce que vous allez renvoyer.
-Mais vous pouvez documenter cela dans votre code, en utilisant : [Réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
+Mais vous pouvez documenter cela dans votre code, en utilisant : [Réponses supplémentaires](additional-responses.md){.internal-link target=_blank}.
-# Guide de l'utilisateur avancé
+# Guide de l'utilisateur avancé { #advanced-user-guide }
-## Caractéristiques supplémentaires
+## Caractéristiques supplémentaires { #additional-features }
Le [Tutoriel - Guide de l'utilisateur](../tutorial/index.md){.internal-link target=_blank} devrait suffire à vous faire découvrir toutes les fonctionnalités principales de **FastAPI**.
Dans les sections suivantes, vous verrez des options, configurations et fonctionnalités supplémentaires.
-/// note | Remarque
+/// tip | Astuce
-Les sections de ce chapitre ne sont **pas nécessairement "avancées"**.
+Les sections suivantes ne sont **pas nécessairement « avancées »**.
-Et il est possible que pour votre cas d'utilisation, la solution se trouve dans l'un d'entre eux.
+Et il est possible que, pour votre cas d'utilisation, la solution se trouve dans l'une d'entre elles.
///
-## Lisez d'abord le didacticiel
+## Lire d'abord le tutoriel { #read-the-tutorial-first }
Vous pouvez utiliser la plupart des fonctionnalités de **FastAPI** grùce aux connaissances du [Tutoriel - Guide de l'utilisateur](../tutorial/index.md){.internal-link target=_blank}.
Et les sections suivantes supposent que vous l'avez lu et que vous en connaissez les idées principales.
-
-## Cours TestDriven.io
-
-Si vous souhaitez suivre un cours pour débutants avancés pour compléter cette section de la documentation, vous pouvez consulter : <a href="https://testdrive.io/courses/tdd-fastapi/" class="external- link" target="_blank">Développement piloté par les tests avec FastAPI et Docker</a> par **TestDriven.io**.
-
-10 % de tous les bĂ©nĂ©fices de ce cours sont reversĂ©s au dĂ©veloppement de **FastAPI**. đ đ
-# Configuration avancée des paramÚtres de chemin
+# Configuration avancée des chemins d'accÚs { #path-operation-advanced-configuration }
-## ID d'opération OpenAPI
+## ID dâopĂ©ration OpenAPI { #openapi-operationid }
-/// warning | Attention
+/// warning | Alertes
-Si vous n'ĂȘtes pas un "expert" en OpenAPI, vous n'en avez probablement pas besoin.
+Si vous nâĂȘtes pas un « expert » dâOpenAPI, vous nâen avez probablement pas besoin.
///
-Dans OpenAPI, les chemins sont des ressources, tels que /users/ ou /items/, exposées par votre API, et les opérations sont les méthodes HTTP utilisées pour manipuler ces chemins, telles que GET, POST ou DELETE. Les operationId sont des chaßnes uniques facultatives utilisées pour identifier une opération d'un chemin. Vous pouvez définir l'OpenAPI `operationId` à utiliser dans votre *opération de chemin* avec le paramÚtre `operation_id`.
+Vous pouvez dĂ©finir lâOpenAPI `operationId` Ă utiliser dans votre chemin dâaccĂšs avec le paramĂštre `operation_id`.
-Vous devez vous assurer qu'il est unique pour chaque opération.
+Vous devez vous assurer quâil est unique pour chaque opĂ©ration.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
-### Utilisation du nom *path operation function* comme operationId
+### Utiliser le nom de la fonction de chemin dâaccĂšs comme operationId { #using-the-path-operation-function-name-as-the-operationid }
-Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer chaque `operation_id` de l'*opération de chemin* en utilisant leur `APIRoute.name`.
+Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer lâ`operation_id` de chaque chemin dâaccĂšs en utilisant leur `APIRoute.name`.
-Vous devriez le faire aprÚs avoir ajouté toutes vos *paramÚtres de chemin*.
+Vous devez le faire aprĂšs avoir ajoutĂ© tous vos chemins dâaccĂšs.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
/// tip | Astuce
-Si vous appelez manuellement `app.openapi()`, vous devez mettre Ă jour les `operationId` avant.
+Si vous appelez manuellement `app.openapi()`, vous devez mettre Ă jour les `operationId` avant cela.
///
-/// warning | Attention
+/// warning | Alertes
-Pour faire cela, vous devez vous assurer que chacun de vos *chemin* ait un nom unique.
+Si vous faites cela, vous devez vous assurer que chacune de vos fonctions de chemin dâaccĂšs a un nom unique.
-MĂȘme s'ils se trouvent dans des modules diffĂ©rents (fichiers Python).
+MĂȘme si elles se trouvent dans des modules diffĂ©rents (fichiers Python).
///
-## Exclusion d'OpenAPI
+## Exclusion dâOpenAPI { #exclude-from-openapi }
-Pour exclure un *chemin* du schéma OpenAPI généré (et donc des systÚmes de documentation automatiques), utilisez le paramÚtre `include_in_schema` et assignez-lui la valeur `False` :
+Pour exclure un chemin dâaccĂšs du schĂ©ma OpenAPI gĂ©nĂ©rĂ© (et donc des systĂšmes de documentation automatiques), utilisez le paramĂštre `include_in_schema` et dĂ©finissez-le Ă `False` :
-{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
-## Description avancée de docstring
+## Description avancée depuis la docstring { #advanced-description-from-docstring }
-Vous pouvez limiter le texte utilisé de la docstring d'une *fonction de chemin* qui sera affiché sur OpenAPI.
+Vous pouvez limiter les lignes utilisĂ©es de la docstring dâune fonction de chemin dâaccĂšs pour OpenAPI.
-L'ajout d'un `\f` (un caractÚre d'échappement "form feed") va permettre à **FastAPI** de tronquer la sortie utilisée pour OpenAPI à ce stade.
+Lâajout dâun `\f` (un caractĂšre « saut de page » Ă©chappĂ©) amĂšne **FastAPI** Ă tronquer la sortie utilisĂ©e pour OpenAPI Ă cet endroit.
-Il n'apparaĂźtra pas dans la documentation, mais d'autres outils (tel que Sphinx) pourront utiliser le reste.
+Cela nâapparaĂźtra pas dans la documentation, mais dâautres outils (comme Sphinx) pourront utiliser le reste.
-{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
-## Réponses supplémentaires
+## Réponses supplémentaires { #additional-responses }
-Vous avez probablement vu comment déclarer le `response_model` et le `status_code` pour une *opération de chemin*.
+Vous avez probablement vu comment dĂ©clarer le `response_model` et le `status_code` pour un chemin dâaccĂšs.
-Cela définit les métadonnées sur la réponse principale d'une *opération de chemin*.
+Cela dĂ©finit les mĂ©tadonnĂ©es sur la rĂ©ponse principale dâun chemin dâaccĂšs.
Vous pouvez également déclarer des réponses supplémentaires avec leurs modÚles, codes de statut, etc.
-Il y a un chapitre entier ici dans la documentation à ce sujet, vous pouvez le lire sur [Réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
+Il y a un chapitre entier dans la documentation à ce sujet, vous pouvez le lire dans [Réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
-## OpenAPI supplémentaire
+## OpenAPI supplémentaire { #openapi-extra }
-Lorsque vous déclarez un *chemin* dans votre application, **FastAPI** génÚre automatiquement les métadonnées concernant ce *chemin* à inclure dans le schéma OpenAPI.
+Lorsque vous dĂ©clarez un chemin dâaccĂšs dans votre application, **FastAPI** gĂ©nĂšre automatiquement les mĂ©tadonnĂ©es pertinentes Ă propos de ce chemin dâaccĂšs Ă inclure dans le schĂ©ma OpenAPI.
/// note | Détails techniques
-La spécification OpenAPI appelle ces métadonnées des <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objets d'opération</a>.
+Dans la spĂ©cification OpenAPI, cela sâappelle lâ<a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">objet Operation</a>.
///
-Il contient toutes les informations sur le *chemin* et est utilisé pour générer automatiquement la documentation.
+Il contient toutes les informations sur le chemin dâaccĂšs et est utilisĂ© pour gĂ©nĂ©rer la documentation automatique.
Il inclut les `tags`, `parameters`, `requestBody`, `responses`, etc.
-Ce schéma OpenAPI spécifique aux *operations* est normalement généré automatiquement par **FastAPI**, mais vous pouvez également l'étendre.
+Ce schĂ©ma OpenAPI spĂ©cifique Ă un chemin dâaccĂšs est normalement gĂ©nĂ©rĂ© automatiquement par **FastAPI**, mais vous pouvez Ă©galement lâĂ©tendre.
/// tip | Astuce
-Si vous avez seulement besoin de déclarer des réponses supplémentaires, un moyen plus pratique de le faire est d'utiliser les [réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
+Ceci est un point dâextension de bas niveau.
+
+Si vous avez seulement besoin de dĂ©clarer des rĂ©ponses supplĂ©mentaires, un moyen plus pratique de le faire est dâutiliser [RĂ©ponses supplĂ©mentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
///
-Vous pouvez étendre le schéma OpenAPI pour une *opération de chemin* en utilisant le paramÚtre `openapi_extra`.
+Vous pouvez Ă©tendre le schĂ©ma OpenAPI pour un chemin dâaccĂšs en utilisant le paramĂštre `openapi_extra`.
-### Extensions OpenAPI
+### Extensions OpenAPI { #openapi-extensions }
-Cet `openapi_extra` peut ĂȘtre utile, par exemple, pour dĂ©clarer [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) :
+Cet `openapi_extra` peut ĂȘtre utile, par exemple, pour dĂ©clarer des [Extensions OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) :
-{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
-Si vous ouvrez la documentation automatique de l'API, votre extension apparaßtra au bas du *chemin* spécifique.
+Si vous ouvrez la documentation automatique de lâAPI, votre extension apparaĂźtra en bas du chemin dâaccĂšs spĂ©cifique.
<img src="/img/tutorial/path-operation-advanced-configuration/image01.png">
-Et dans le fichier openapi généré (`/openapi.json`), vous verrez également votre extension dans le cadre du *chemin* spécifique :
+Et si vous consultez lâOpenAPI rĂ©sultant (Ă `/openapi.json` dans votre API), vous verrez Ă©galement votre extension comme partie du chemin dâaccĂšs spĂ©cifique :
```JSON hl_lines="22"
{
- "openapi": "3.0.2",
+ "openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
}
```
-### Personnalisation du Schéma OpenAPI pour un chemin
+### Personnaliser le schĂ©ma OpenAPI dâun chemin dâaccĂšs { #custom-openapi-path-operation-schema }
-Le dictionnaire contenu dans la variable `openapi_extra` sera fusionné avec le schéma OpenAPI généré automatiquement pour l'*opération de chemin*.
+Le dictionnaire dans `openapi_extra` sera fusionnĂ© en profondeur avec le schĂ©ma OpenAPI gĂ©nĂ©rĂ© automatiquement pour le chemin dâaccĂšs.
Ainsi, vous pouvez ajouter des données supplémentaires au schéma généré automatiquement.
-Par exemple, vous pouvez dĂ©cider de lire et de valider la requĂȘte avec votre propre code, sans utiliser les fonctionnalitĂ©s automatiques de validation proposĂ©e par Pydantic, mais vous pouvez toujours dĂ©finir la requĂȘte dans le schĂ©ma OpenAPI.
+Par exemple, vous pourriez dĂ©cider de lire et de valider la requĂȘte avec votre propre code, sans utiliser les fonctionnalitĂ©s automatiques de FastAPI avec Pydantic, mais vous pourriez tout de mĂȘme vouloir dĂ©finir la requĂȘte dans le schĂ©ma OpenAPI.
-Vous pouvez le faire avec `openapi_extra`Â :
+Vous pourriez le faire avec `openapi_extra` :
-{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[20:37,39:40] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
-Dans cet exemple, nous n'avons dĂ©clarĂ© aucun modĂšle Pydantic. En fait, le corps de la requĂȘte n'est mĂȘme pas <abbr title="converti d'un format simple, comme des octets, en objets Python">parsĂ©</abbr> en tant que JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargĂ© de l'analyser d'une maniĂšre ou d'une autre.
+Dans cet exemple, nous nâavons dĂ©clarĂ© aucun modĂšle Pydantic. En fait, le corps de la requĂȘte nâest mĂȘme pas <abbr title="converti d'un format simple, comme des octets, en objets Python">parsĂ©</abbr> en JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargĂ©e de lâanalyser dâune maniĂšre ou dâune autre.
NĂ©anmoins, nous pouvons dĂ©clarer le schĂ©ma attendu pour le corps de la requĂȘte.
-### Type de contenu OpenAPI personnalisé
+### Type de contenu OpenAPI personnalisé { #custom-openapi-content-type }
-En utilisant cette mĂȘme astuce, vous pouvez utiliser un modĂšle Pydantic pour dĂ©finir le schĂ©ma JSON qui est ensuite inclus dans la section de schĂ©ma OpenAPI personnalisĂ©e pour le *chemin* concernĂ©.
+En utilisant cette mĂȘme astuce, vous pourriez utiliser un modĂšle Pydantic pour dĂ©finir le JSON Schema qui est ensuite inclus dans la section de schĂ©ma OpenAPI personnalisĂ©e pour le chemin dâaccĂšs.
-Et vous pouvez le faire mĂȘme si le type de donnĂ©es dans la requĂȘte n'est pas au format JSON.
+Et vous pourriez le faire mĂȘme si le type de donnĂ©es dans la requĂȘte nâest pas du JSON.
-Dans cet exemple, nous n'utilisons pas les fonctionnalitĂ©s de FastAPI pour extraire le schĂ©ma JSON des modĂšles Pydantic ni la validation automatique pour JSON. En fait, nous dĂ©clarons le type de contenu de la requĂȘte en tant que YAML, et non JSON :
+Par exemple, dans cette application nous nâutilisons pas la fonctionnalitĂ© intĂ©grĂ©e de FastAPI pour extraire le JSON Schema des modĂšles Pydantic ni la validation automatique pour le JSON. En fait, nous dĂ©clarons le type de contenu de la requĂȘte comme YAML, pas JSON :
-{* ../../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] *}
-Néanmoins, bien que nous n'utilisions pas la fonctionnalité par défaut, nous utilisons toujours un modÚle Pydantic pour générer manuellement le schéma JSON pour les données que nous souhaitons recevoir en YAML.
+NĂ©anmoins, bien que nous nâutilisions pas la fonctionnalitĂ© intĂ©grĂ©e par dĂ©faut, nous utilisons toujours un modĂšle Pydantic pour gĂ©nĂ©rer manuellement le JSON Schema pour les donnĂ©es que nous souhaitons recevoir en YAML.
-Ensuite, nous utilisons directement la requĂȘte et extrayons son contenu en tant qu'octets. Cela signifie que FastAPI n'essaiera mĂȘme pas d'analyser le payload de la requĂȘte en tant que JSON.
+Ensuite, nous utilisons directement la requĂȘte et extrayons le corps en tant que `bytes`. Cela signifie que FastAPI nâessaiera mĂȘme pas dâanalyser le payload de la requĂȘte en JSON.
-Et nous analysons directement ce contenu YAML, puis nous utilisons Ă nouveau le mĂȘme modĂšle Pydantic pour valider le contenu YAMLÂ :
+Ensuite, dans notre code, nous analysons directement ce contenu YAML, puis nous utilisons Ă nouveau le mĂȘme modĂšle Pydantic pour valider le contenu YAML :
-{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *}
+{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
/// tip | Astuce
Ici, nous rĂ©utilisons le mĂȘme modĂšle Pydantic.
-Mais nous aurions pu tout aussi bien pu le valider d'une autre maniĂšre.
+Mais de la mĂȘme maniĂšre, nous aurions pu le valider autrement.
///
-# Renvoyer directement une réponse
+# Renvoyer directement une réponse { #return-a-response-directly }
-Lorsque vous créez une *opération de chemins* **FastAPI**, vous pouvez normalement retourner n'importe quelle donnée : un `dict`, une `list`, un modÚle Pydantic, un modÚle de base de données, etc.
+Lorsque vous créez un *chemin d'accÚs* **FastAPI**, vous pouvez normalement retourner n'importe quelle donnée : un `dict`, une `list`, un modÚle Pydantic, un modÚle de base de données, etc.
-Par défaut, **FastAPI** convertirait automatiquement cette valeur de retour en JSON en utilisant le `jsonable_encoder` expliqué dans [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
+Par défaut, **FastAPI** convertirait automatiquement cette valeur de retour en JSON en utilisant le `jsonable_encoder` expliqué dans [Encodeur compatible JSON](../tutorial/encoder.md){.internal-link target=_blank}.
Ensuite, en arriÚre-plan, il mettra ces données JSON-compatible (par exemple un `dict`) à l'intérieur d'un `JSONResponse` qui sera utilisé pour envoyer la réponse au client.
-Mais vous pouvez retourner une `JSONResponse` directement à partir de vos *opérations de chemin*.
+Mais vous pouvez retourner une `JSONResponse` directement Ă partir de vos *chemins d'accĂšs*.
Cela peut ĂȘtre utile, par exemple, pour retourner des en-tĂȘtes personnalisĂ©s ou des cookies.
-## Renvoyer une `Response`
+## Renvoyer une `Response` { #return-a-response }
En fait, vous pouvez retourner n'importe quelle `Response` ou n'importe quelle sous-classe de celle-ci.
-/// note | Remarque
+/// tip | Astuce
`JSONResponse` est elle-mĂȘme une sous-classe de `Response`.
Elle ne fera aucune conversion de données avec les modÚles Pydantic, elle ne convertira pas le contenu en un type quelconque.
-Cela vous donne beaucoup de flexibilité. Vous pouvez retourner n'importe quel type de données, surcharger n'importe quelle déclaration ou validation de données.
+Cela vous donne beaucoup de flexibilité. Vous pouvez retourner n'importe quel type de données, surcharger n'importe quelle déclaration ou validation de données, etc.
-## Utiliser le `jsonable_encoder` dans une `Response`
+## Utiliser le `jsonable_encoder` dans une `Response` { #using-the-jsonable-encoder-in-a-response }
-Parce que **FastAPI** n'apporte aucune modification Ă une `Response` que vous retournez, vous devez vous assurer que son contenu est prĂȘt Ă ĂȘtre utilisĂ© (sĂ©rialisable).
+Parce que **FastAPI** n'apporte aucune modification Ă une `Response` que vous retournez, vous devez vous assurer que son contenu est prĂȘt pour cela.
Par exemple, vous ne pouvez pas mettre un modÚle Pydantic dans une `JSONResponse` sans d'abord le convertir en un `dict` avec tous les types de données (comme `datetime`, `UUID`, etc.) convertis en types compatibles avec JSON.
-Pour ces cas, vous pouvez spécifier un appel à `jsonable_encoder` pour convertir vos données avant de les passer à une réponse :
+Pour ces cas, vous pouvez utiliser le `jsonable_encoder` pour convertir vos données avant de les passer à une réponse :
-{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *}
+{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *}
/// note | Détails techniques
Vous pouvez aussi utiliser `from starlette.responses import JSONResponse`.
-**FastAPI** fournit le mĂȘme objet `starlette.responses` que `fastapi.responses` juste par commoditĂ© pour le dĂ©veloppeur. Mais la plupart des rĂ©ponses disponibles proviennent directement de Starlette.
+**FastAPI** fournit le mĂȘme `starlette.responses` que `fastapi.responses` juste par commoditĂ© pour vous, le dĂ©veloppeur. Mais la plupart des rĂ©ponses disponibles proviennent directement de Starlette.
///
-## Renvoyer une `Response` personnalisée
+## Renvoyer une `Response` personnalisée { #returning-a-custom-response }
L'exemple ci-dessus montre toutes les parties dont vous avez besoin, mais il n'est pas encore trÚs utile, car vous auriez pu retourner l'`item` directement, et **FastAPI** l'aurait mis dans une `JSONResponse` pour vous, en le convertissant en `dict`, etc. Tout cela par défaut.
Vous pouvez mettre votre contenu XML dans une chaĂźne de caractĂšres, la placer dans une `Response`, et la retourner :
-{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
+{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
-## Notes
+## Notes { #notes }
Lorsque vous renvoyez une `Response` directement, ses données ne sont pas validées, converties (sérialisées), ni documentées automatiquement.
-# Test de performance
+# Tests de performance { #benchmarks }
-Les tests de performance de TechEmpower montrent que les applications **FastAPI** tournant sous Uvicorn comme <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">Ă©tant l'un des frameworks Python les plus rapides disponibles</a>, seulement infĂ©rieur Ă Starlette et Uvicorn (tous deux utilisĂ©s au cĆur de FastAPI). (*)
+Les benchmarks indĂ©pendants de TechEmpower montrent que les applications **FastAPI** sâexĂ©cutant avec Uvicorn sont <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">parmi les frameworks Python les plus rapides disponibles</a>, seulement en dessous de Starlette et Uvicorn euxâmĂȘmes (tous deux utilisĂ©s en interne par FastAPI).
-Mais en prĂȘtant attention aux tests de performance et aux comparaisons, il faut tenir compte de ce qu'il suit.
+Mais en prĂȘtant attention aux tests de performance et aux comparaisons, vous devez tenir compte de ce qui suit.
-## Tests de performance et rapidité
+## Tests de performance et rapidité { #benchmarks-and-speed }
Lorsque vous vérifiez les tests de performance, il est commun de voir plusieurs outils de différents types comparés comme équivalents.
En particulier, on voit Uvicorn, Starlette et FastAPI comparés (parmi de nombreux autres outils).
-Plus le problÚme résolu par un outil est simple, mieux seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalités additionnelles fournies par les outils.
+Plus le problÚme résolu par un outil est simple, meilleures seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalités additionnelles fournies par les outils.
La hiérarchie est la suivante :
* **Uvicorn** : un serveur ASGI
- * **Starlette** : (utilise Uvicorn) un micro-framework web
- * **FastAPI**: (utilise Starlette) un micro-framework pour API disposant de fonctionnalités additionnelles pour la création d'API, avec la validation des données, etc.
+ * **Starlette** : (utilise Uvicorn) un microframework web
+ * **FastAPI**: (utilise Starlette) un microframework pour API disposant de fonctionnalités additionnelles pour la création d'API, avec la validation des données, etc.
* **Uvicorn** :
- * A les meilleures performances, Ă©tant donnĂ© qu'il n'a pas beaucoup de code mis-Ă -part le serveur en lui-mĂȘme.
- * On n'Ă©crit pas une application avec uniquement Uvicorn. Cela signifie que le code devrait inclure plus ou moins, au minimum, tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale apportera les mĂȘmes complications que si on avait utilisĂ© un framework et que l'on avait minimisĂ© la quantitĂ© de code et de bugs.
- * Si on compare Uvicorn, il faut le comparer Ă d'autre applications de serveurs comme Daphne, Hypercorn, uWSGI, etc.
+ * A les meilleures performances, Ă©tant donnĂ© qu'il n'a pas beaucoup de code mis Ă part le serveur en luiâmĂȘme.
+ * On n'Ă©crit pas une application directement avec Uvicorn. Cela signifie que le code devrait inclure, au minimum, plus ou moins tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale aura la mĂȘme surcharge que si on avait utilisĂ© un framework, tout en minimisant la quantitĂ© de code et les bugs.
+ * Si on compare Uvicorn, il faut le comparer Ă d'autres serveurs d'applications comme Daphne, Hypercorn, uWSGI, etc.
* **Starlette** :
- * A les seconde meilleures performances aprĂšs Uvicorn. Starlette utilise en rĂ©alitĂ© Uvicorn. De ce fait, il ne peut quâĂȘtre plus "lent" qu'Uvicorn car il requiert l'exĂ©cution de plus de code.
- * Cependant il nous apporte les outils pour construire une application web simple, avec un routage basé sur des chemins, etc.
- * Si on compare Starlette, il faut le comparer Ă d'autres frameworks web (ou micorframework) comme Sanic, Flask, Django, etc.
+ * A les secondes meilleures performances aprĂšs Uvicorn. En rĂ©alitĂ©, Starlette utilise Uvicorn. De ce fait, il ne peut quâĂȘtre plus « lent » qu'Uvicorn car il requiert l'exĂ©cution de plus de code.
+ * Cependant, il apporte les outils pour construire une application web simple, avec un routage basé sur des chemins, etc.
+ * Si on compare Starlette, il faut le comparer Ă d'autres frameworks web (ou microframeworks) comme Sanic, Flask, Django, etc.
* **FastAPI** :
- * Comme Starlette, FastAPI utilise Uvicorn et ne peut donc pas ĂȘtre plus rapide que ce dernier.
- * FastAPI apporte des fonctionnalitĂ©s supplĂ©mentaires Ă Starlette. Des fonctionnalitĂ©s qui sont nĂ©cessaires presque systĂ©matiquement lors de la crĂ©ation d'une API, comme la validation des donnĂ©es, la sĂ©rialisation. En utilisant FastAPI, on obtient une documentation automatiquement (qui ne requiert aucune manipulation pour ĂȘtre mise en place).
- * Si on n'utilisait pas FastAPI mais directement Starlette (ou un outil Ă©quivalent comme Sanic, Flask, Responder, etc) il faudrait implĂ©menter la validation des donnĂ©es et la sĂ©rialisation par nous-mĂȘme. Le rĂ©sultat serait donc le mĂȘme dans les deux cas mais du travail supplĂ©mentaire serait Ă rĂ©aliser avec Starlette, surtout en considĂ©rant que la validation des donnĂ©es et la sĂ©rialisation reprĂ©sentent la plus grande quantitĂ© de code Ă Ă©crire dans une application.
- * De ce fait, en utilisant FastAPI on minimise le temps de dĂ©veloppement, les bugs, le nombre de lignes de code, et on obtient les mĂȘmes performances (si ce n'est de meilleurs performances) que l'on aurait pu avoir sans ce framework (en ayant Ă implĂ©menter de nombreuses fonctionnalitĂ©s importantes par nous-mĂȘmes).
- * Si on compare FastAPI, il faut le comparer à d'autres frameworks web (ou ensemble d'outils) qui fournissent la validation des données, la sérialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc.
+ * Comme Starlette utilise Uvicorn et ne peut donc pas ĂȘtre plus rapide que lui, **FastAPI** utilise Starlette et ne peut donc pas ĂȘtre plus rapide que lui.
+ * FastAPI apporte des fonctionnalitĂ©s supplĂ©mentaires Ă Starlette. Des fonctionnalitĂ©s dont vous avez presque toujours besoin lors de la crĂ©ation d'une API, comme la validation des donnĂ©es et la sĂ©rialisation. En l'utilisant, vous obtenez une documentation automatique « gratuitement » (la documentation automatique n'ajoute mĂȘme pas de surcharge Ă lâexĂ©cution, elle est gĂ©nĂ©rĂ©e au dĂ©marrage).
+ * Si on n'utilisait pas FastAPI mais directement Starlette (ou un autre outil comme Sanic, Flask, Responder, etc.), il faudrait implĂ©menter toute la validation des donnĂ©es et la sĂ©rialisation soiâmĂȘme. L'application finale aurait donc la mĂȘme surcharge que si elle avait Ă©tĂ© construite avec FastAPI. Et dans de nombreux cas, cette validation des donnĂ©es et cette sĂ©rialisation reprĂ©sentent la plus grande quantitĂ© de code Ă©crite dans les applications.
+ * De ce fait, en utilisant FastAPI on minimise le temps de dĂ©veloppement, les bugs, le nombre de lignes de code, et on obtient probablement les mĂȘmes performances (voire de meilleures performances) que l'on aurait pu avoir sans ce framework (car il aurait fallu tout implĂ©menter dans votre code).
+ * Si on compare FastAPI, il faut le comparer Ă d'autres frameworks dâapplication web (ou ensembles d'outils) qui fournissent la validation des donnĂ©es, la sĂ©rialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc. Des frameworks avec validation des donnĂ©es, sĂ©rialisation et documentation automatiques intĂ©grĂ©es.
-# Déployer avec Docker
+# FastAPI dans des conteneurs - Docker { #fastapi-in-containers-docker }
-Dans cette section, vous verrez des instructions et des liens vers des guides pour savoir comment :
+Lors du déploiement d'applications FastAPI, une approche courante consiste à construire une **image de conteneur Linux**. C'est généralement fait avec <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Vous pouvez ensuite déployer cette image de conteneur de plusieurs façons possibles.
-* Faire de votre application **FastAPI** une image/conteneur Docker avec une performance maximale. En environ **5 min**.
-* (Optionnellement) comprendre ce que vous, en tant que développeur, devez savoir sur HTTPS.
-* Configurer un cluster en mode Docker Swarm avec HTTPS automatique, mĂȘme sur un simple serveur Ă 5 dollars US/mois. En environ **20 min**.
-* Générer et déployer une application **FastAPI** complÚte, en utilisant votre cluster Docker Swarm, avec HTTPS, etc. En environ **10 min**.
+L'utilisation de conteneurs Linux présente plusieurs avantages, notamment la **sécurité**, la **réplicabilité**, la **simplicité**, entre autres.
-Vous pouvez utiliser <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> pour le déploiement. Il présente plusieurs avantages comme la sécurité, la réplicabilité, la simplicité de développement, etc.
-
-Si vous utilisez Docker, vous pouvez utiliser l'image Docker officielle :
+/// tip | Astuce
-## <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>
+Vous ĂȘtes pressĂ© et vous connaissez dĂ©jĂ tout ça ? Allez directement au [`Dockerfile` ci-dessous đ](#build-a-docker-image-for-fastapi).
-Cette image est dotée d'un mécanisme d'"auto-tuning", de sorte qu'il vous suffit d'ajouter votre code pour obtenir automatiquement des performances trÚs élevées. Et sans faire de sacrifices.
+///
-Mais vous pouvez toujours changer et mettre Ă jour toutes les configurations avec des variables d'environnement ou des fichiers de configuration.
+<details>
+<summary>Aperçu du Dockerfile đ</summary>
-/// tip | Astuce
+```Dockerfile
+FROM python:3.9
-Pour voir toutes les configurations et options, rendez-vous sur la page de l'image Docker : <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
+WORKDIR /code
-///
+COPY ./requirements.txt /code/requirements.txt
-## Créer un `Dockerfile`
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
-* Allez dans le répertoire de votre projet.
-* Créez un `Dockerfile` avec :
+COPY ./app /code/app
-```Dockerfile
-FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
+CMD ["fastapi", "run", "app/main.py", "--port", "80"]
-COPY ./app /app
+# Si vous exécutez derriÚre un proxy comme Nginx ou Traefik, ajoutez --proxy-headers
+# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"]
```
-### Applications plus larges
+</details>
-Si vous avez suivi la section sur la création d' [Applications avec plusieurs fichiers](../tutorial/bigger-applications.md){.internal-link target=_blank}, votre `Dockerfile` pourrait ressembler à ceci :
+## Qu'est-ce qu'un conteneur { #what-is-a-container }
-```Dockerfile
-FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
+Les conteneurs (principalement les conteneurs Linux) sont un moyen trĂšs **lĂ©ger** d'empaqueter des applications, y compris toutes leurs dĂ©pendances et les fichiers nĂ©cessaires, tout en les isolant des autres conteneurs (autres applications ou composants) dans le mĂȘme systĂšme.
-COPY ./app /app/app
-```
+Les conteneurs Linux s'exĂ©cutent en utilisant le mĂȘme noyau Linux que l'hĂŽte (machine, machine virtuelle, serveur cloud, etc.). Cela signifie simplement qu'ils sont trĂšs lĂ©gers (comparĂ©s Ă des machines virtuelles complĂštes Ă©mulant un systĂšme d'exploitation entier).
-### Raspberry Pi et autres architectures
+Ainsi, les conteneurs consomment **peu de ressources**, une quantité comparable à l'exécution directe des processus (alors qu'une machine virtuelle consommerait beaucoup plus).
-Si vous utilisez Docker sur un Raspberry Pi (qui a un processeur ARM) ou toute autre architecture, vous pouvez créer un `Dockerfile` à partir de zéro, basé sur une image de base Python (qui est multi-architecture) et utiliser Uvicorn seul.
+Les conteneurs ont également leurs propres processus d'exécution **isolés** (généralement un seul processus), leur systÚme de fichiers et leur réseau, ce qui simplifie le déploiement, la sécurité, le développement, etc.
-Dans ce cas, votre `Dockerfile` pourrait ressembler à ceci :
+## Qu'est-ce qu'une image de conteneur { #what-is-a-container-image }
-```Dockerfile
-FROM python:3.7
+Un **conteneur** s'exécute à partir d'une **image de conteneur**.
+
+Une image de conteneur est une version **statique** de tous les fichiers, des variables d'environnement et de la commande/le programme par dĂ©faut devant ĂȘtre prĂ©sents dans un conteneur. Ici, **statique** signifie que l'**image** du conteneur ne s'exĂ©cute pas, elle n'est pas en cours d'exĂ©cution, ce ne sont que les fichiers et mĂ©tadonnĂ©es empaquetĂ©s.
+
+Par opposition à une « **image de conteneur** » qui correspond aux contenus statiques stockés, un « **conteneur** » fait normalement référence à l'instance en cours d'exécution, la chose qui est **exécutée**.
+
+Lorsque le **conteneur** est démarré et en cours d'exécution (démarré à partir d'une **image de conteneur**), il peut créer ou modifier des fichiers, des variables d'environnement, etc. Ces changements n'existeront que dans ce conteneur, mais ne persisteront pas dans l'image de conteneur sous-jacente (ils ne seront pas enregistrés sur le disque).
+
+Une image de conteneur est comparable au **programme** et Ă ses contenus, par exemple `python` et un fichier `main.py`.
+
+Et le **conteneur** lui-mĂȘme (par opposition Ă l'**image de conteneur**) est l'instance en cours d'exĂ©cution rĂ©elle de l'image, comparable Ă un **processus**. En fait, un conteneur ne fonctionne que lorsqu'il a un **processus en cours d'exĂ©cution** (et normalement, il s'agit d'un seul processus). Le conteneur s'arrĂȘte lorsqu'aucun processus n'y est en cours d'exĂ©cution.
+
+## Images de conteneur { #container-images }
+
+Docker a été l'un des principaux outils pour créer et gérer des **images de conteneur** et des **conteneurs**.
+
+Et il existe un <a href="https://hub.docker.com/" class="external-link" target="_blank">Docker Hub</a> public avec des **images de conteneur officielles** pré-construites pour de nombreux outils, environnements, bases de données et applications.
+
+Par exemple, il existe une <a href="https://hub.docker.com/_/python" class="external-link" target="_blank">image Python officielle</a>.
+
+Et il existe beaucoup d'autres images pour différentes choses comme des bases de données, par exemple :
+
+* <a href="https://hub.docker.com/_/postgres" class="external-link" target="_blank">PostgreSQL</a>
+* <a href="https://hub.docker.com/_/mysql" class="external-link" target="_blank">MySQL</a>
+* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
+* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a>, etc.
+
+En utilisant une image de conteneur pré-construite, il est trÚs facile de **combiner** et d'utiliser différents outils. Par exemple, pour essayer une nouvelle base de données. Dans la plupart des cas, vous pouvez utiliser les **images officielles** et simplement les configurer avec des variables d'environnement.
+
+Ainsi, dans de nombreux cas, vous pouvez apprendre les conteneurs et Docker et réutiliser ces connaissances avec de nombreux outils et composants différents.
+
+Vous exécuteriez donc **plusieurs conteneurs** avec des éléments différents, comme une base de données, une application Python, un serveur web avec une application frontend React, et les connecter entre eux via leur réseau interne.
+
+Tous les systÚmes de gestion de conteneurs (comme Docker ou Kubernetes) disposent de ces fonctionnalités réseau intégrées.
+
+## Conteneurs et processus { #containers-and-processes }
+
+Une **image de conteneur** inclut normalement dans ses métadonnées le programme/la commande par défaut à exécuter lorsque le **conteneur** est démarré et les paramÚtres à transmettre à ce programme. TrÚs similaire à ce que vous utiliseriez en ligne de commande.
+
+Lorsqu'un **conteneur** est démarré, il exécutera cette commande/ce programme (bien que vous puissiez la/le remplacer et faire exécuter une autre commande/un autre programme).
+
+Un conteneur fonctionne tant que le **processus principal** (commande ou programme) est en cours d'exécution.
+
+Un conteneur a normalement un **seul processus**, mais il est aussi possible de dĂ©marrer des sous-processus Ă partir du processus principal, et ainsi vous aurez **plusieurs processus** dans le mĂȘme conteneur.
-RUN pip install fastapi uvicorn
+Mais il n'est pas possible d'avoir un conteneur en cours d'exĂ©cution sans **au moins un processus en cours**. Si le processus principal s'arrĂȘte, le conteneur s'arrĂȘte.
-EXPOSE 80
+## Construire une image Docker pour FastAPI { #build-a-docker-image-for-fastapi }
-COPY ./app /app
+TrĂšs bien, construisons quelque chose maintenant ! đ
-CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+Je vais vous montrer comment construire une **image Docker** pour FastAPI **à partir de zéro**, basée sur l'image **officielle Python**.
+
+C'est ce que vous voudrez faire dans **la plupart des cas**, par exemple :
+
+* Utiliser **Kubernetes** ou des outils similaires
+* Exécuter sur un **Raspberry Pi**
+* Utiliser un service cloud qui exécuterait une image de conteneur pour vous, etc.
+
+### Dépendances des paquets { #package-requirements }
+
+Vous aurez normalement les **dépendances des paquets** de votre application dans un fichier.
+
+Cela dépendra principalement de l'outil que vous utilisez pour **installer** ces dépendances.
+
+La maniĂšre la plus courante consiste Ă avoir un fichier `requirements.txt` avec les noms des paquets et leurs versions, un par ligne.
+
+Vous utiliserez bien sĂ»r les mĂȘmes idĂ©es que vous avez lues dans [Ă propos des versions de FastAPI](versions.md){.internal-link target=_blank} pour dĂ©finir les plages de versions.
+
+Par exemple, votre `requirements.txt` pourrait ressembler Ă :
+
+```
+fastapi[standard]>=0.113.0,<0.114.0
+pydantic>=2.7.0,<3.0.0
```
-## Créer le code **FastAPI**.
+Et vous installerez normalement ces dépendances de paquets avec `pip`, par exemple :
-* Créer un répertoire `app` et y entrer.
-* Créez un fichier `main.py` avec :
+<div class="termy">
-```Python
-from typing import Optional
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic
+```
+</div>
+
+/// info
+
+Il existe d'autres formats et outils pour définir et installer des dépendances de paquets.
+
+///
+
+### Créer le code **FastAPI** { #create-the-fastapi-code }
+
+* Créez un répertoire `app` et entrez dedans.
+* Créez un fichier vide `__init__.py`.
+* Créez un fichier `main.py` avec :
+
+```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Optional[str] = None):
+def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
-* Vous devriez maintenant avoir une structure de répertoire telle que :
+### Dockerfile { #dockerfile }
+
+Maintenant, dans le mĂȘme rĂ©pertoire de projet, crĂ©ez un fichier `Dockerfile` avec :
+
+```{ .dockerfile .annotate }
+# (1)!
+FROM python:3.9
+
+# (2)!
+WORKDIR /code
+
+# (3)!
+COPY ./requirements.txt /code/requirements.txt
+
+# (4)!
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (5)!
+COPY ./app /code/app
+
+# (6)!
+CMD ["fastapi", "run", "app/main.py", "--port", "80"]
+```
+
+1. Démarrer à partir de l'image de base Python officielle.
+
+2. Définir le répertoire de travail courant sur `/code`.
+
+ C'est là que nous placerons le fichier `requirements.txt` et le répertoire `app`.
+
+3. Copier le fichier des dépendances vers le répertoire `/code`.
+
+ Copier **uniquement** le fichier des dépendances en premier, pas le reste du code.
+
+ Comme ce fichier **ne change pas souvent**, Docker le détectera et utilisera le **cache** pour cette étape, ce qui activera le cache pour l'étape suivante aussi.
+
+4. Installer les dépendances listées dans le fichier des dépendances.
+
+ L'option `--no-cache-dir` indique Ă `pip` de ne pas enregistrer localement les paquets tĂ©lĂ©chargĂ©s, car cela ne sert que si `pip` devait ĂȘtre relancĂ© pour installer les mĂȘmes paquets, mais ce n'est pas le cas lorsque l'on travaille avec des conteneurs.
+
+ /// note | Remarque
+
+ Le `--no-cache-dir` concerne uniquement `pip`, cela n'a rien Ă voir avec Docker ou les conteneurs.
+
+ ///
+
+ L'option `--upgrade` indique à `pip` de mettre à niveau les paquets s'ils sont déjà installés.
+
+ Comme l'Ă©tape prĂ©cĂ©dente de copie du fichier peut ĂȘtre dĂ©tectĂ©e par le **cache Docker**, cette Ă©tape **utilisera Ă©galement le cache Docker** lorsqu'il est disponible.
+
+ L'utilisation du cache à cette étape vous **fera gagner** beaucoup de **temps** lors de la reconstruction de l'image encore et encore pendant le développement, au lieu de **télécharger et installer** toutes les dépendances **à chaque fois**.
+
+5. Copier le répertoire `./app` dans le répertoire `/code`.
+
+ Comme cela contient tout le code qui est ce qui **change le plus fréquemment**, le **cache** Docker ne sera pas facilement utilisé pour cette étape ou pour les **étapes suivantes**.
+
+ Il est donc important de placer cela **vers la fin** du `Dockerfile`, pour optimiser les temps de construction de l'image de conteneur.
+
+6. Définir la **commande** pour utiliser `fastapi run`, qui utilise Uvicorn sous le capot.
+
+ `CMD` prend une liste de chaßnes, chacune de ces chaßnes correspond à ce que vous taperiez en ligne de commande séparé par des espaces.
+
+ Cette commande sera exĂ©cutĂ©e Ă partir du **rĂ©pertoire de travail courant**, le mĂȘme rĂ©pertoire `/code` que vous avez dĂ©fini plus haut avec `WORKDIR /code`.
+
+/// tip | Astuce
+
+Passez en revue ce que fait chaque ligne en cliquant sur chaque bulle numĂ©rotĂ©e dans le code. đ
+
+///
+
+/// warning | Alertes
+
+Vous devez vous assurer d'utiliser **toujours** la **forme exec** de l'instruction `CMD`, comme expliqué ci-dessous.
+
+///
+
+#### Utiliser `CMD` - Forme Exec { #use-cmd-exec-form }
+
+L'instruction Docker <a href="https://docs.docker.com/reference/dockerfile/#cmd" class="external-link" target="_blank">`CMD`</a> peut ĂȘtre Ă©crite sous deux formes :
+
+â
Forme **Exec** :
+
+```Dockerfile
+# â
Ă faire
+CMD ["fastapi", "run", "app/main.py", "--port", "80"]
+```
+
+âïž Forme **Shell** :
+
+```Dockerfile
+# âïž Ă ne pas faire
+CMD fastapi run app/main.py --port 80
+```
+
+Assurez-vous d'utiliser toujours la forme **exec** pour garantir que FastAPI peut s'arrĂȘter proprement et que les [Ă©vĂ©nements de cycle de vie](../advanced/events.md){.internal-link target=_blank} sont dĂ©clenchĂ©s.
+
+Vous pouvez en lire davantage dans la <a href="https://docs.docker.com/reference/dockerfile/#shell-and-exec-form" class="external-link" target="_blank">documentation Docker sur les formes shell et exec</a>.
+
+Cela peut ĂȘtre trĂšs visible lors de l'utilisation de `docker compose`. Voir cette section de la FAQ Docker Compose pour plus de dĂ©tails techniques : <a href="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop" class="external-link" target="_blank">Pourquoi mes services mettent-ils 10 secondes Ă se recrĂ©er ou Ă s'arrĂȘter ?</a>.
+
+#### Structure du répertoire { #directory-structure }
+
+Vous devriez maintenant avoir une structure de répertoire comme :
```
.
âââ app
+â  âââ __init__.py
â âââ main.py
-âââ Dockerfile
+âââ Dockerfile
+âââ requirements.txt
+```
+
+#### DerriĂšre un proxy de terminaison TLS { #behind-a-tls-termination-proxy }
+
+Si vous exĂ©cutez votre conteneur derriĂšre un proxy de terminaison TLS (load balancer) comme Nginx ou Traefik, ajoutez l'option `--proxy-headers`, cela indiquera Ă Uvicorn (via la CLI FastAPI) de faire confiance aux en-tĂȘtes envoyĂ©s par ce proxy lui indiquant que l'application s'exĂ©cute derriĂšre HTTPS, etc.
+
+```Dockerfile
+CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
+```
+
+#### Cache Docker { #docker-cache }
+
+Il y a une astuce importante dans ce `Dockerfile`, nous copions d'abord **le fichier des dépendances seul**, pas le reste du code. Laissez-moi vous expliquer pourquoi.
+
+```Dockerfile
+COPY ./requirements.txt /code/requirements.txt
+```
+
+Docker et d'autres outils **construisent** ces images de conteneur **de maniÚre incrémentale**, en ajoutant **une couche au-dessus de l'autre**, en commençant par le haut du `Dockerfile` et en ajoutant tous les fichiers créés par chacune des instructions du `Dockerfile`.
+
+Docker et des outils similaires utilisent Ă©galement un **cache interne** lors de la construction de l'image : si un fichier n'a pas changĂ© depuis la derniĂšre construction de l'image de conteneur, alors il va **rĂ©utiliser la mĂȘme couche** créée la derniĂšre fois, au lieu de recopier le fichier et crĂ©er une nouvelle couche Ă partir de zĂ©ro.
+
+Ăviter simplement la copie des fichiers n'amĂ©liore pas nĂ©cessairement les choses de maniĂšre significative, mais comme il a utilisĂ© le cache pour cette Ă©tape, il peut **utiliser le cache pour l'Ă©tape suivante**. Par exemple, il peut utiliser le cache pour l'instruction qui installe les dĂ©pendances avec :
+
+```Dockerfile
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
```
-## Construire l'image Docker
+Le fichier des dépendances **ne changera pas fréquemment**. Ainsi, en copiant uniquement ce fichier, Docker pourra **utiliser le cache** pour cette étape.
+
+Et ensuite, Docker pourra **utiliser le cache pour l'Ă©tape suivante** qui tĂ©lĂ©charge et installe ces dĂ©pendances. Et c'est lĂ que nous **gagnons beaucoup de temps**. âš ... et Ă©vitons l'ennui en attendant. đȘđ
-* Allez dans le répertoire du projet (dans lequel se trouve votre `Dockerfile`, contenant votre répertoire `app`).
+Télécharger et installer les dépendances de paquets **peut prendre des minutes**, mais utiliser le **cache** ne **prendra que quelques secondes** au plus.
+
+Et comme vous reconstruirez l'image de conteneur encore et encore pendant le développement pour vérifier que vos modifications de code fonctionnent, cela vous fera gagner beaucoup de temps cumulé.
+
+Ensuite, vers la fin du `Dockerfile`, nous copions tout le code. Comme c'est ce qui **change le plus fréquemment**, nous le plaçons vers la fin, car presque toujours, tout ce qui suit cette étape ne pourra pas utiliser le cache.
+
+```Dockerfile
+COPY ./app /code/app
+```
+
+### Construire l'image Docker { #build-the-docker-image }
+
+Maintenant que tous les fichiers sont en place, construisons l'image de conteneur.
+
+* Allez dans le rĂ©pertoire du projet (lĂ oĂč se trouve votre `Dockerfile`, contenant votre rĂ©pertoire `app`).
* Construisez votre image FastAPI :
<div class="termy">
</div>
-## Démarrer le conteneur Docker
+/// tip | Astuce
+
+Remarquez le `.` à la fin, équivalent à `./`, il indique à Docker le répertoire à utiliser pour construire l'image de conteneur.
+
+Dans ce cas, c'est le mĂȘme rĂ©pertoire courant (`.`).
-* Exécutez un conteneur basé sur votre image :
+///
+
+### Démarrer le conteneur Docker { #start-the-docker-container }
+
+* Exécutez un conteneur basé sur votre image :
<div class="termy">
</div>
-Vous disposez maintenant d'un serveur FastAPI optimisé dans un conteneur Docker. Configuré automatiquement pour votre
-serveur actuel (et le nombre de cĆurs du CPU).
-
-## Vérifier
+## Vérifier { #check-it }
-Vous devriez pouvoir accéder à votre application via l'URL de votre conteneur Docker, par exemple : <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou équivalent, en utilisant votre hÎte Docker).
+Vous devriez pouvoir le vérifier via l'URL de votre conteneur Docker, par exemple : <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou équivalent, en utilisant votre hÎte Docker).
-Vous verrez quelque chose comme :
+Vous verrez quelque chose comme :
```JSON
{"item_id": 5, "q": "somequery"}
```
-## Documentation interactive de l'API
+## Documentation interactive de l'API { #interactive-api-docs }
-Vous pouvez maintenant visiter <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou équivalent, en utilisant votre hÎte Docker).
+Vous pouvez maintenant aller sur <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou équivalent, en utilisant votre hÎte Docker).
-Vous verrez la documentation interactive automatique de l'API (fournie par <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>)Â :
+Vous verrez la documentation interactive automatique de l'API (fournie par <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>) :

-## Documentation de l'API alternative
+## Documentation alternative de l'API { #alternative-api-docs }
-Et vous pouvez également aller sur <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou équivalent, en utilisant votre hÎte Docker).
+Et vous pouvez aussi aller sur <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou équivalent, en utilisant votre hÎte Docker).
-Vous verrez la documentation automatique alternative (fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>)Â :
+Vous verrez la documentation automatique alternative (fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :

-## Traefik
+## Construire une image Docker avec un FastAPI mono-fichier { #build-a-docker-image-with-a-single-file-fastapi }
+
+Si votre FastAPI est un seul fichier, par exemple `main.py` sans répertoire `./app`, votre structure de fichiers pourrait ressembler à ceci :
+
+```
+.
+âââ Dockerfile
+âââ main.py
+âââ requirements.txt
+```
+
+Vous n'auriez alors qu'Ă changer les chemins correspondants pour copier le fichier dans le `Dockerfile` :
+
+```{ .dockerfile .annotate hl_lines="10 13" }
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (1)!
+COPY ./main.py /code/
-<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> est un reverse proxy/load balancer
-haute performance. Il peut faire office de "Proxy de terminaison TLS" (entre autres fonctionnalités).
+# (2)!
+CMD ["fastapi", "run", "main.py", "--port", "80"]
+```
+
+1. Copier le fichier `main.py` directement dans le répertoire `/code` (sans répertoire `./app`).
+
+2. Utiliser `fastapi run` pour servir votre application dans le fichier unique `main.py`.
+
+Lorsque vous passez le fichier Ă `fastapi run`, il dĂ©tectera automatiquement qu'il s'agit d'un fichier unique et non d'un package et saura comment l'importer et servir votre application FastAPI. đ
+
+## Concepts de déploiement { #deployment-concepts }
+
+Parlons Ă nouveau de certains des mĂȘmes [Concepts de dĂ©ploiement](concepts.md){.internal-link target=_blank} en termes de conteneurs.
+
+Les conteneurs sont principalement un outil pour simplifier le processus de **construction et de déploiement** d'une application, mais ils n'imposent pas une approche particuliÚre pour gérer ces **concepts de déploiement**, et il existe plusieurs stratégies possibles.
+
+La **bonne nouvelle**, c'est qu'avec chaque stratĂ©gie diffĂ©rente, il existe un moyen de couvrir tous les concepts de dĂ©ploiement. đ
+
+Passons en revue ces **concepts de déploiement** en termes de conteneurs :
+
+* HTTPS
+* Exécution au démarrage
+* Redémarrages
+* Réplication (le nombre de processus en cours d'exécution)
+* Mémoire
+* Ătapes prĂ©alables au dĂ©marrage
+
+## HTTPS { #https }
+
+Si l'on se concentre uniquement sur l'**image de conteneur** pour une application FastAPI (et plus tard sur le **conteneur** en cours d'exécution), HTTPS serait normalement géré **à l'extérieur** par un autre outil.
+
+Cela pourrait ĂȘtre un autre conteneur, par exemple avec <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>, gĂ©rant **HTTPS** et l'acquisition **automatique** des **certificats**.
+
+/// tip | Astuce
-Il est intégré à Let's Encrypt. Ainsi, il peut gérer toutes les parties HTTPS, y compris l'acquisition et le renouvellement des certificats.
+Traefik s'intĂšgre avec Docker, Kubernetes, et d'autres, donc il est trĂšs facile de configurer HTTPS pour vos conteneurs avec lui.
-Il est également intégré à Docker. Ainsi, vous pouvez déclarer vos domaines dans les configurations de chaque application et faire en sorte qu'elles lisent ces configurations, génÚrent les certificats HTTPS et servent via HTTPS à votre application automatiquement, sans nécessiter aucune modification de leurs configurations.
+///
+
+Alternativement, HTTPS pourrait ĂȘtre gĂ©rĂ© par un fournisseur cloud comme l'un de leurs services (tout en exĂ©cutant l'application dans un conteneur).
+
+## Exécution au démarrage et redémarrages { #running-on-startup-and-restarts }
+
+Il y a normalement un autre outil chargé de **démarrer et exécuter** votre conteneur.
+
+Cela pourrait ĂȘtre **Docker** directement, **Docker Compose**, **Kubernetes**, un **service cloud**, etc.
+
+Dans la plupart (ou toutes) des situations, il existe une option simple pour activer l'exécution du conteneur au démarrage et activer les redémarrages en cas d'échec. Par exemple, dans Docker, c'est l'option de ligne de commande `--restart`.
+
+Sans utiliser de conteneurs, faire en sorte que les applications s'exĂ©cutent au dĂ©marrage et avec redĂ©marrages peut ĂȘtre fastidieux et difficile. Mais en **travaillant avec des conteneurs**, dans la plupart des cas, cette fonctionnalitĂ© est incluse par dĂ©faut. âš
+
+## Réplication - Nombre de processus { #replication-number-of-processes }
+
+Si vous avez un <abbr title="Un groupe de machines configurĂ©es pour ĂȘtre connectĂ©es et fonctionner ensemble d'une certaine maniĂšre.">cluster</abbr> de machines avec **Kubernetes**, Docker Swarm Mode, Nomad, ou un autre systĂšme complexe similaire pour gĂ©rer des conteneurs distribuĂ©s sur plusieurs machines, alors vous voudrez probablement **gĂ©rer la rĂ©plication** au **niveau du cluster** plutĂŽt que d'utiliser un **gestionnaire de processus** (comme Uvicorn avec workers) dans chaque conteneur.
+
+L'un de ces systĂšmes de gestion de conteneurs distribuĂ©s comme Kubernetes dispose normalement d'une maniĂšre intĂ©grĂ©e de gĂ©rer la **rĂ©plication des conteneurs** tout en supportant l'**Ă©quilibrage de charge** des requĂȘtes entrantes. Le tout au **niveau du cluster**.
+
+Dans ces cas, vous voudrez probablement construire une **image Docker à partir de zéro** comme [expliqué ci-dessus](#dockerfile), en installant vos dépendances et en exécutant **un seul processus Uvicorn** au lieu d'utiliser plusieurs workers Uvicorn.
+
+### Ăquilibreur de charge { #load-balancer }
+
+Lors de l'utilisation de conteneurs, vous aurez normalement un composant **Ă l'Ă©coute sur le port principal**. Cela pourrait ĂȘtre un autre conteneur qui est Ă©galement un **proxy de terminaison TLS** pour gĂ©rer **HTTPS** ou un outil similaire.
+
+Comme ce composant prend la **charge** des requĂȘtes et la distribue entre les workers de façon (espĂ©rons-le) **Ă©quilibrĂ©e**, on l'appelle Ă©galement communĂ©ment un **Ă©quilibreur de charge**.
+
+/// tip | Astuce
+
+Le mĂȘme composant de **proxy de terminaison TLS** utilisĂ© pour HTTPS sera probablement aussi un **Ă©quilibreur de charge**.
+
+///
+
+Et en travaillant avec des conteneurs, le mĂȘme systĂšme que vous utilisez pour les dĂ©marrer et les gĂ©rer dispose dĂ©jĂ d'outils internes pour transmettre la **communication rĂ©seau** (par ex. les requĂȘtes HTTP) depuis cet **Ă©quilibreur de charge** (qui peut aussi ĂȘtre un **proxy de terminaison TLS**) vers le ou les conteneurs avec votre application.
+
+### Un équilibreur de charge - Plusieurs conteneurs worker { #one-load-balancer-multiple-worker-containers }
+
+Lorsque vous travaillez avec **Kubernetes** ou des systĂšmes de gestion de conteneurs distribuĂ©s similaires, l'utilisation de leurs mĂ©canismes rĂ©seau internes permet au **seul Ă©quilibreur de charge** Ă l'Ă©coute sur le **port** principal de transmettre la communication (les requĂȘtes) vers potentiellement **plusieurs conteneurs** exĂ©cutant votre application.
+
+Chacun de ces conteneurs exĂ©cutant votre application aura normalement **un seul processus** (par ex. un processus Uvicorn exĂ©cutant votre application FastAPI). Ils seront tous des **conteneurs identiques**, exĂ©cutant la mĂȘme chose, mais chacun avec son propre processus, sa mĂ©moire, etc. De cette façon, vous profiterez de la **parallĂ©lisation** sur **diffĂ©rents cĆurs** du CPU, voire sur **diffĂ©rentes machines**.
+
+Et le systĂšme de conteneurs distribuĂ©s avec l'**Ă©quilibreur de charge** **distribuera les requĂȘtes** Ă chacun des conteneurs exĂ©cutant votre application **Ă tour de rĂŽle**. Ainsi, chaque requĂȘte pourrait ĂȘtre traitĂ©e par l'un des multiples **conteneurs rĂ©pliquĂ©s** exĂ©cutant votre application.
+
+Et normalement cet **Ă©quilibreur de charge** pourra gĂ©rer des requĂȘtes qui vont vers *d'autres* applications dans votre cluster (par ex. vers un autre domaine, ou sous un autre prĂ©fixe de chemin d'URL), et transmettra cette communication aux bons conteneurs pour *cette autre* application s'exĂ©cutant dans votre cluster.
+
+### Un processus par conteneur { #one-process-per-container }
+
+Dans ce type de scénario, vous voudrez probablement avoir **un seul processus (Uvicorn) par conteneur**, puisque vous gérez déjà la réplication au niveau du cluster.
+
+Donc, dans ce cas, vous **ne voudrez pas** avoir plusieurs workers dans le conteneur, par exemple avec l'option de ligne de commande `--workers`. Vous voudrez avoir **un seul processus Uvicorn** par conteneur (mais probablement plusieurs conteneurs).
+
+Avoir un autre gestionnaire de processus à l'intérieur du conteneur (comme ce serait le cas avec plusieurs workers) n'ajouterait que de la **complexité inutile** que vous gérez trÚs probablement déjà avec votre systÚme de cluster.
+
+### Conteneurs avec plusieurs processus et cas particuliers { #containers-with-multiple-processes-and-special-cases }
+
+Bien sĂ»r, il existe des **cas particuliers** oĂč vous pourriez vouloir avoir **un conteneur** avec plusieurs **processus worker Uvicorn** Ă l'intĂ©rieur.
+
+Dans ces cas, vous pouvez utiliser l'option de ligne de commande `--workers` pour définir le nombre de workers que vous souhaitez exécuter :
+
+```{ .dockerfile .annotate }
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+COPY ./app /code/app
+
+# (1)!
+CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
+```
+
+1. Ici, nous utilisons l'option de ligne de commande `--workers` pour définir le nombre de workers à 4.
+
+Voici quelques exemples oĂč cela pourrait avoir du sens :
+
+#### Une application simple { #a-simple-app }
+
+Vous pourriez vouloir un gestionnaire de processus dans le conteneur si votre application est **suffisamment simple** pour s'exécuter sur un **seul serveur**, pas un cluster.
+
+#### Docker Compose { #docker-compose }
+
+Vous pourriez déployer sur un **seul serveur** (pas un cluster) avec **Docker Compose**, donc vous n'auriez pas un moyen simple de gérer la réplication des conteneurs (avec Docker Compose) tout en préservant le réseau partagé et l'**équilibrage de charge**.
+
+Vous pourriez alors vouloir avoir **un seul conteneur** avec un **gestionnaire de processus** qui démarre **plusieurs processus worker** à l'intérieur.
---
-Avec ces informations et ces outils, passez Ă la section suivante pour tout combiner.
+L'idée principale est que **rien** de tout cela ne sont des **rÚgles gravées dans la pierre** que vous devez suivre aveuglément. Vous pouvez utiliser ces idées pour **évaluer votre propre cas d'usage** et décider de la meilleure approche pour votre systÚme, en vérifiant comment gérer les concepts suivants :
+
+* 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Ă©alables au dĂ©marrage
+
+## Mémoire { #memory }
+
+Si vous exécutez **un seul processus par conteneur**, vous aurez une quantité de mémoire consommée plus ou moins bien définie, stable et limitée par chacun de ces conteneurs (plus d'un s'ils sont répliqués).
+
+Vous pouvez alors dĂ©finir ces mĂȘmes limites et exigences de mĂ©moire dans vos configurations pour votre systĂšme de gestion de conteneurs (par exemple dans **Kubernetes**). De cette façon, il pourra **rĂ©pliquer les conteneurs** sur les **machines disponibles** en tenant compte de la quantitĂ© de mĂ©moire dont ils ont besoin et de la quantitĂ© disponible sur les machines du cluster.
+
+Si votre application est **simple**, cela ne sera probablement **pas un problĂšme**, et vous n'aurez peut-ĂȘtre pas besoin de spĂ©cifier des limites de mĂ©moire strictes. Mais si vous **utilisez beaucoup de mĂ©moire** (par exemple avec des modĂšles de **machine learning**), vous devez vĂ©rifier combien de mĂ©moire vous consommez et ajuster le **nombre de conteneurs** qui s'exĂ©cutent sur **chaque machine** (et peut-ĂȘtre ajouter plus de machines Ă votre cluster).
+
+Si vous exécutez **plusieurs processus par conteneur**, vous devez vous assurer que le nombre de processus démarrés ne **consomme pas plus de mémoire** que ce qui est disponible.
+
+## Ătapes prĂ©alables au dĂ©marrage et conteneurs { #previous-steps-before-starting-and-containers }
+
+Si vous utilisez des conteneurs (par ex. Docker, Kubernetes), alors il existe deux approches principales que vous pouvez utiliser.
+
+### Plusieurs conteneurs { #multiple-containers }
+
+Si vous avez **plusieurs conteneurs**, probablement chacun exécutant un **seul processus** (par exemple, dans un cluster **Kubernetes**), alors vous voudrez probablement avoir un **conteneur séparé** effectuant le travail des **étapes préalables** dans un seul conteneur, exécutant un seul processus, **avant** d'exécuter les conteneurs worker répliqués.
+
+/// info
+
+Si vous utilisez Kubernetes, ce sera probablement un <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>.
+
+///
+
+Si, dans votre cas d'usage, il n'y a pas de problĂšme Ă exĂ©cuter ces Ă©tapes prĂ©alables **plusieurs fois en parallĂšle** (par exemple si vous n'exĂ©cutez pas de migrations de base de donnĂ©es, mais vĂ©rifiez simplement si la base de donnĂ©es est prĂȘte), alors vous pourriez aussi simplement les mettre dans chaque conteneur juste avant de dĂ©marrer le processus principal.
+
+### Un seul conteneur { #single-container }
+
+Si vous avez une configuration simple, avec **un seul conteneur** qui dĂ©marre ensuite plusieurs **processus worker** (ou un seul processus aussi), vous pouvez alors exĂ©cuter ces Ă©tapes prĂ©alables dans le mĂȘme conteneur, juste avant de dĂ©marrer le processus avec l'application.
+
+### Image Docker de base { #base-docker-image }
+
+Il existait une image Docker officielle FastAPI : <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Mais elle est dĂ©sormais dĂ©prĂ©ciĂ©e. âïž
+
+Vous ne devriez probablement **pas** utiliser cette image Docker de base (ni aucune autre similaire).
+
+Si vous utilisez **Kubernetes** (ou autres) et que vous définissez déjà la **réplication** au niveau du cluster, avec plusieurs **conteneurs**. Dans ces cas, il est préférable de **construire une image à partir de zéro** comme décrit ci-dessus : [Construire une image Docker pour FastAPI](#build-a-docker-image-for-fastapi).
+
+Et si vous devez avoir plusieurs workers, vous pouvez simplement utiliser l'option de ligne de commande `--workers`.
+
+/// note | Détails techniques
+
+L'image Docker a Ă©tĂ© créée Ă une Ă©poque oĂč Uvicorn ne supportait pas la gestion et le redĂ©marrage des workers morts, il fallait donc utiliser Gunicorn avec Uvicorn, ce qui ajoutait pas mal de complexitĂ©, uniquement pour que Gunicorn gĂšre et redĂ©marre les processus worker Uvicorn.
+
+Mais maintenant qu'Uvicorn (et la commande `fastapi`) supporte l'usage de `--workers`, il n'y a plus de raison d'utiliser une image Docker de base au lieu de construire la vĂŽtre (c'est Ă peu prĂšs la mĂȘme quantitĂ© de code đ
).
+
+///
+
+## Déployer l'image de conteneur { #deploy-the-container-image }
-## Cluster en mode Docker Swarm avec Traefik et HTTPS
+AprÚs avoir une image de conteneur (Docker), il existe plusieurs façons de la déployer.
-Vous pouvez avoir un cluster en mode Docker Swarm configuré en quelques minutes (environ 20 min) avec un processus Traefik principal gérant HTTPS (y compris l'acquisition et le renouvellement des certificats).
+Par exemple :
-En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut mĂȘme s'agir
-d'un serveur à 5 USD/mois) et ensuite vous pouvez vous développer autant que vous le souhaitez en ajoutant d'autres serveurs.
+* Avec **Docker Compose** sur un seul serveur
+* Avec un cluster **Kubernetes**
+* Avec un cluster Docker Swarm Mode
+* Avec un autre outil comme Nomad
+* Avec un service cloud qui prend votre image de conteneur et la déploie
-Pour configurer un cluster en mode Docker Swarm avec Traefik et la gestion de HTTPS, suivez ce guide :
+## Image Docker avec `uv` { #docker-image-with-uv }
-### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode et Traefik pour un cluster HTTPS</a>
+Si vous utilisez <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a> pour installer et gérer votre projet, vous pouvez suivre leur <a href="https://docs.astral.sh/uv/guides/integration/docker/" class="external-link" target="_blank">guide Docker pour uv</a>.
-### Déployer une application FastAPI
+## Récapitulatif { #recap }
-La façon la plus simple de tout mettre en place, serait d'utiliser les [**Générateurs de projet FastAPI**](../project-generation.md){.internal-link target=_blank}.
+Avec les systÚmes de conteneurs (par ex. avec **Docker** et **Kubernetes**), il devient assez simple de gérer tous les **concepts de déploiement** :
-Le gĂ©nerateur de projet adĂ©quat est conçu pour ĂȘtre intĂ©grĂ© Ă ce cluster Docker Swarm avec Traefik et HTTPS dĂ©crit ci-dessus.
+* HTTPS
+* Exécution au démarrage
+* Redémarrages
+* Réplication (le nombre de processus en cours d'exécution)
+* Mémoire
+* Ătapes prĂ©alables au dĂ©marrage
-Vous pouvez générer un projet en 2 min environ.
+Dans la plupart des cas, vous ne voudrez probablement pas utiliser d'image de base, et au contraire **construire une image de conteneur à partir de zéro** basée sur l'image Docker Python officielle.
-Le projet généré a des instructions pour le déployer et le faire prend 2 min de plus.
+En prenant soin de l'**ordre** des instructions dans le `Dockerfile` et du **cache Docker**, vous pouvez **minimiser les temps de construction**, maximiser votre productivitĂ© (et Ă©viter l'ennui). đ
-# Ă propos de HTTPS
+# Ă propos de HTTPS { #about-https }
-Il est facile de penser que HTTPS peut simplement ĂȘtre "activĂ©" ou non.
+Il est facile de supposer que HTTPS est quelque chose qui est simplement « activé » ou non.
Mais c'est beaucoup plus complexe que cela.
-/// tip
+/// tip | Astuce
-Si vous ĂȘtes pressĂ© ou si cela ne vous intĂ©resse pas, passez aux sections suivantes pour obtenir des instructions Ă©tape par Ă©tape afin de tout configurer avec diffĂ©rentes techniques.
+Si vous ĂȘtes pressĂ© ou si cela ne vous intĂ©resse pas, continuez avec les sections suivantes pour obtenir des instructions Ă©tape par Ă©tape afin de tout configurer avec diffĂ©rentes techniques.
///
-Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez <a href="https://howhttps.works/"
-class="external-link" target="_blank">https://howhttps.works/</a>.
+Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
Maintenant, du point de vue d'un dĂ©veloppeur, voici plusieurs choses Ă avoir en tĂȘte en pensant au HTTPS :
-* Pour le HTTPS, le serveur a besoin de "certificats" générés par une tierce partie.
- * Ces certificats sont en fait acquis auprÚs de la tierce partie, et non "générés".
-* Les certificats ont une durée de vie.
- * Ils expirent.
- * Puis ils doivent ĂȘtre renouvelĂ©s et acquis Ă nouveau auprĂšs de la tierce partie.
-* Le cryptage de la connexion se fait au niveau du protocole TCP.
- * C'est une couche en dessous de HTTP.
- * Donc, le certificat et le traitement du cryptage sont faits avant HTTP.
-* TCP ne connaĂźt pas les "domaines", seulement les adresses IP.
- * L'information sur le domaine spécifique demandé se trouve dans les données HTTP.
-* Les certificats HTTPS "certifient" un certain domaine, mais le protocole et le cryptage se font au niveau TCP, avant de savoir quel domaine est traité.
-* Par défaut, cela signifie que vous ne pouvez avoir qu'un seul certificat HTTPS par adresse IP.
- * Quelle que soit la taille de votre serveur ou la taille de chacune des applications qu'il contient.
- * Il existe cependant une solution Ă ce problĂšme.
-* Il existe une extension du protocole TLS (celui qui gÚre le cryptage au niveau TCP, avant HTTP) appelée <a
- href="https://fr.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr
- title="Server Name Indication (indication du nom du serveur)">SNI (indication du nom du serveur)</abbr></a>.
- * Cette extension SNI permet Ă un seul serveur (avec une seule adresse IP) d'avoir plusieurs certificats HTTPS et de servir plusieurs domaines/applications HTTPS.
- * Pour que cela fonctionne, un seul composant (programme) fonctionnant sur le serveur, écoutant sur l'adresse IP publique, doit avoir tous les certificats HTTPS du serveur.
-* AprÚs avoir obtenu une connexion sécurisée, le protocole de communication est toujours HTTP.
- * Le contenu est cryptĂ©, mĂȘme s'il est envoyĂ© avec le protocole HTTP.
-
-Il est courant d'avoir un seul programme/serveur HTTP fonctionnant sur le serveur (la machine, l'hĂŽte, etc.) et
-gĂ©rant toutes les parties HTTPS : envoyer les requĂȘtes HTTP dĂ©cryptĂ©es Ă l'application HTTP rĂ©elle fonctionnant sur
-le mĂȘme serveur (dans ce cas, l'application **FastAPI**), prendre la rĂ©ponse HTTP de l'application, la crypter en utilisant le certificat appropriĂ© et la renvoyer au client en utilisant HTTPS. Ce serveur est souvent appelĂ© un <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de terminaison TLS</a>.
-
-## Let's Encrypt
-
-Avant Let's Encrypt, ces certificats HTTPS étaient vendus par des tiers de confiance.
-
-Le processus d'acquisition d'un de ces certificats était auparavant lourd, nécessitait pas mal de paperasses et les certificats étaient assez chers.
-
-Mais ensuite, <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> a été créé.
-
-Il s'agit d'un projet de la Fondation Linux. Il fournit des certificats HTTPS gratuitement. De maniÚre automatisée. Ces certificats utilisent toutes les sécurités cryptographiques standard et ont une durée de vie courte (environ 3 mois), de sorte que la sécurité est en fait meilleure en raison de leur durée de vie réduite.
+* Pour le HTTPS, **le serveur** doit **disposer de « certificats »** générés par une **tierce partie**.
+ * Ces certificats sont en réalité **acquis** auprÚs de la tierce partie, et non « générés ».
+* Les certificats ont une **durée de vie**.
+ * Ils **expirent**.
+ * Puis ils doivent ĂȘtre **renouvelĂ©s**, **acquis Ă nouveau** auprĂšs de la tierce partie.
+* Le cryptage de la connexion se fait au **niveau TCP**.
+ * C'est une couche **en dessous de HTTP**.
+ * Donc, la gestion du **certificat et du cryptage** est effectuée **avant HTTP**.
+* **TCP ne connaßt pas les « domaines »**. Il ne connaßt que les adresses IP.
+ * L'information sur le **domaine spécifique** demandé se trouve dans les **données HTTP**.
+* Les **certificats HTTPS** « certifient » un **certain domaine**, mais le protocole et le cryptage se font au niveau TCP, **avant de savoir** quel domaine est traité.
+* **Par défaut**, cela signifie que vous ne pouvez avoir qu'**un seul certificat HTTPS par adresse IP**.
+ * Quelle que soit la taille de votre serveur ou la petitesse de chacune des applications qu'il contient.
+ * Il existe cependant une **solution** Ă ce problĂšme.
+* Il existe une **extension** du protocole **TLS** (celui qui gÚre le cryptage au niveau TCP, avant HTTP) appelée **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication - Indication du nom du serveur">SNI</abbr></a>**.
+ * Cette extension SNI permet Ă un seul serveur (avec une **seule adresse IP**) d'avoir **plusieurs certificats HTTPS** et de servir **plusieurs domaines/applications HTTPS**.
+ * Pour que cela fonctionne, un **seul** composant (programme) fonctionnant sur le serveur, écoutant sur l'**adresse IP publique**, doit avoir **tous les certificats HTTPS** du serveur.
+* **AprÚs** l'établissement d'une connexion sécurisée, le protocole de communication est **toujours HTTP**.
+ * Le contenu est **cryptĂ©**, mĂȘme s'il est envoyĂ© avec le **protocole HTTP**.
+
+Il est courant d'avoir **un seul programme/serveur HTTP** fonctionnant sur le serveur (la machine, l'hĂŽte, etc.) et **gĂ©rant toutes les parties HTTPS** : recevoir les **requĂȘtes HTTPS chiffrĂ©es**, envoyer les **requĂȘtes HTTP dĂ©chiffrĂ©es** Ă l'application HTTP rĂ©elle fonctionnant sur le mĂȘme serveur (l'application **FastAPI**, dans ce cas), prendre la **rĂ©ponse HTTP** de l'application, la **chiffrer** en utilisant le **certificat HTTPS** appropriĂ© et la renvoyer au client en utilisant **HTTPS**. Ce serveur est souvent appelĂ© un **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de terminaison TLS</a>**.
+
+Parmi les options que vous pourriez utiliser comme Proxy de terminaison TLSÂ :
+
+* Traefik (qui peut également gérer les renouvellements de certificats)
+* Caddy (qui peut également gérer les renouvellements de certificats)
+* Nginx
+* HAProxy
+
+## Let's Encrypt { #lets-encrypt }
+
+Avant Let's Encrypt, ces **certificats HTTPS** étaient vendus par des tiers de confiance.
+
+Le processus d'acquisition de l'un de ces certificats était auparavant lourd, nécessitait pas mal de paperasses et les certificats étaient assez chers.
+
+Mais ensuite, **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** a été créé.
+
+Il s'agit d'un projet de la Fondation Linux. Il fournit **des certificats HTTPS gratuitement**, de maniÚre automatisée. Ces certificats utilisent toutes les sécurités cryptographiques standard et ont une durée de vie courte (environ 3 mois), de sorte que la **sécurité est en fait meilleure** en raison de leur durée de vie réduite.
Les domaines sont vérifiés de maniÚre sécurisée et les certificats sont générés automatiquement. Cela permet également d'automatiser le renouvellement de ces certificats.
-L'idée est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un HTTPS sécurisé, gratuitement et pour toujours.
+L'idée est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un **HTTPS sécurisé, gratuitement et pour toujours**.
+
+## HTTPS pour les développeurs { #https-for-developers }
+
+Voici un exemple de ce à quoi pourrait ressembler une API HTTPS, étape par étape, en portant principalement attention aux idées importantes pour les développeurs.
+
+### Nom de domaine { #domain-name }
+
+Tout commencerait probablement par le fait que vous **acquĂ©riez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le mĂȘme que votre fournisseur cloud).
+
+Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP **publique** <abbr title="Qui ne change pas">fixe</abbr>.
+
+Dans le ou les serveurs DNS, vous configureriez un enregistrement (un « `A record` ») pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**.
+
+Vous feriez probablement cela une seule fois, la premiĂšre fois, lors de la mise en place de l'ensemble.
+
+/// tip | Astuce
+
+Cette partie relative au nom de domaine intervient bien avant HTTPS, mais comme tout dépend du domaine et de l'adresse IP, il vaut la peine de la mentionner ici.
+
+///
+
+### DNS { #dns }
+
+Concentrons-nous maintenant sur toutes les parties réellement liées à HTTPS.
+
+D'abord, le navigateur vérifierait auprÚs des **serveurs DNS** quelle est l'**IP du domaine**, dans ce cas, `someapp.example.com`.
+
+Les serveurs DNS indiqueraient au navigateur d'utiliser une **adresse IP** spécifique. Ce serait l'adresse IP publique utilisée par votre serveur, celle que vous avez configurée dans les serveurs DNS.
+
+<img src="/img/deployment/https/https01.drawio.svg">
+
+### Début de la négociation TLS (Handshake) { #tls-handshake-start }
+
+Le navigateur communiquerait ensuite avec cette adresse IP sur le **port 443** (le port HTTPS).
+
+La premiÚre partie de la communication consiste simplement à établir la connexion entre le client et le serveur et à décider des clés cryptographiques qu'ils utiliseront, etc.
+
+<img src="/img/deployment/https/https02.drawio.svg">
+
+Cette interaction entre le client et le serveur pour établir la connexion TLS s'appelle la **négociation TLS (TLS handshake)**.
+
+### TLS avec l'extension SNI { #tls-with-sni-extension }
+
+**Un seul processus** sur le serveur peut Ă©couter sur un **port** spĂ©cifique d'une **adresse IP** spĂ©cifique. Il pourrait y avoir d'autres processus Ă©coutant sur d'autres ports de la mĂȘme adresse IP, mais un seul pour chaque combinaison d'adresse IP et de port.
+
+TLS (HTTPS) utilise par défaut le port spécifique `443`. C'est donc le port dont nous aurions besoin.
+
+Comme un seul processus peut écouter sur ce port, le processus qui le ferait serait le **Proxy de terminaison TLS**.
+
+Le Proxy de terminaison TLS aurait accĂšs Ă un ou plusieurs **certificats TLS** (certificats HTTPS).
+
+En utilisant l'**extension SNI** mentionnée plus haut, le Proxy de terminaison TLS vérifierait lequel des certificats TLS (HTTPS) disponibles il devrait utiliser pour cette connexion, en choisissant celui qui correspond au domaine attendu par le client.
+
+Dans ce cas, il utiliserait le certificat pour `someapp.example.com`.
+
+<img src="/img/deployment/https/https03.drawio.svg">
+
+Le client **fait déjà confiance** à l'entité qui a généré ce certificat TLS (dans ce cas Let's Encrypt, mais nous y reviendrons plus tard), il peut donc **vérifier** que le certificat est valide.
+
+Ensuite, en utilisant le certificat, le client et le Proxy de terminaison TLS **décident comment chiffrer** le reste de la **communication TCP**. Cela termine la partie **négociation TLS**.
+
+AprÚs cela, le client et le serveur disposent d'une **connexion TCP chiffrée**, c'est ce que fournit TLS. Ils peuvent alors utiliser cette connexion pour démarrer la **communication HTTP** proprement dite.
+
+Et c'est ce qu'est **HTTPS** : c'est simplement du **HTTP** à l'intérieur d'une **connexion TLS sécurisée** au lieu d'une connexion TCP pure (non chiffrée).
+
+/// tip | Astuce
+
+Remarquez que le cryptage de la communication se produit au **niveau TCP**, pas au niveau HTTP.
+
+///
+
+### RequĂȘte HTTPS { #https-request }
+
+Maintenant que le client et le serveur (spécifiquement le navigateur et le Proxy de terminaison TLS) ont une **connexion TCP chiffrée**, ils peuvent démarrer la **communication HTTP**.
+
+Ainsi, le client envoie une **requĂȘte HTTPS**. Ce n'est qu'une requĂȘte HTTP Ă travers une connexion TLS chiffrĂ©e.
+
+<img src="/img/deployment/https/https04.drawio.svg">
+
+### DĂ©chiffrer la requĂȘte { #decrypt-the-request }
+
+Le Proxy de terminaison TLS utiliserait le chiffrement convenu pour **dĂ©chiffrer la requĂȘte**, et transmettrait la **requĂȘte HTTP en clair (dĂ©chiffrĂ©e)** au processus exĂ©cutant l'application (par exemple un processus avec Uvicorn exĂ©cutant l'application FastAPI).
+
+<img src="/img/deployment/https/https05.drawio.svg">
+
+### Réponse HTTP { #http-response }
+
+L'application traiterait la requĂȘte et enverrait une **rĂ©ponse HTTP en clair (non chiffrĂ©e)** au Proxy de terminaison TLS.
+
+<img src="/img/deployment/https/https06.drawio.svg">
+
+### Réponse HTTPS { #https-response }
+
+Le Proxy de terminaison TLS **chiffrerait ensuite la réponse** en utilisant la cryptographie convenue auparavant (qui a commencé avec le certificat pour `someapp.example.com`), et la renverrait au navigateur.
+
+Ensuite, le navigateur vérifierait que la réponse est valide et chiffrée avec la bonne clé cryptographique, etc. Il **déchiffrerait la réponse** et la traiterait.
+
+<img src="/img/deployment/https/https07.drawio.svg">
+
+Le client (navigateur) saura que la réponse provient du bon serveur parce qu'elle utilise la cryptographie convenue auparavant à l'aide du **certificat HTTPS**.
+
+### Applications multiples { #multiple-applications }
+
+Sur le mĂȘme serveur (ou les mĂȘmes serveurs), il pourrait y avoir **plusieurs applications**, par exemple d'autres programmes d'API ou une base de donnĂ©es.
+
+Un seul processus peut gĂ©rer l'adresse IP et le port spĂ©cifiques (le Proxy de terminaison TLS dans notre exemple), mais les autres applications/processus peuvent Ă©galement s'exĂ©cuter sur le ou les serveurs, tant qu'ils n'essaient pas d'utiliser la mĂȘme **combinaison d'adresse IP publique et de port**.
+
+<img src="/img/deployment/https/https08.drawio.svg">
+
+De cette façon, le Proxy de terminaison TLS pourrait gĂ©rer HTTPS et les certificats pour **plusieurs domaines**, pour plusieurs applications, puis transmettre les requĂȘtes Ă la bonne application dans chaque cas.
+
+### Renouvellement des certificats { #certificate-renewal }
+
+à un moment donné dans le futur, chaque certificat **expirerait** (environ 3 mois aprÚs son acquisition).
+
+Ensuite, il y aurait un autre programme (dans certains cas c'est un autre programme, dans d'autres cas cela pourrait ĂȘtre le mĂȘme Proxy de terminaison TLS) qui communiquerait avec Let's Encrypt et renouvellerait le ou les certificats.
+
+<img src="/img/deployment/https/https.drawio.svg">
+
+Les **certificats TLS** sont **associés à un nom de domaine**, pas à une adresse IP.
+
+Ainsi, pour renouveler les certificats, le programme de renouvellement doit **prouver** à l'autorité (Let's Encrypt) qu'il **« possÚde » et contrÎle ce domaine**.
+
+Pour ce faire, et pour s'adapter aux différents besoins des applications, il existe plusieurs façons de procéder. Parmi les plus courantes :
+
+* **Modifier certains enregistrements DNS**.
+ * Pour cela, le programme de renouvellement doit prendre en charge les API du fournisseur DNSÂ ; ainsi, selon le fournisseur DNS que vous utilisez, cela peut ĂȘtre ou non une option.
+* **S'exécuter comme un serveur** (au moins pendant le processus d'acquisition du certificat) sur l'adresse IP publique associée au domaine.
+ * Comme nous l'avons dit plus haut, un seul processus peut écouter sur une adresse IP et un port spécifiques.
+ * C'est l'une des raisons pour lesquelles il est trĂšs utile que le mĂȘme Proxy de terminaison TLS prenne Ă©galement en charge le processus de renouvellement des certificats.
+ * Sinon, vous pourriez avoir Ă arrĂȘter le Proxy de terminaison TLS momentanĂ©ment, dĂ©marrer le programme de renouvellement pour acquĂ©rir les certificats, puis les configurer avec le Proxy de terminaison TLS, et ensuite redĂ©marrer le Proxy de terminaison TLS. Ce n'est pas idĂ©al, car votre/vos application(s) ne seront pas disponibles pendant le temps oĂč le Proxy de terminaison TLS est arrĂȘtĂ©.
+
+Tout ce processus de renouvellement, tout en continuant à servir l'application, est l'une des principales raisons pour lesquelles vous voudriez avoir un **systÚme séparé pour gérer HTTPS** avec un Proxy de terminaison TLS, au lieu d'utiliser directement les certificats TLS avec le serveur d'application (par exemple Uvicorn).
+
+## En-tĂȘtes Proxy Forwarded { #proxy-forwarded-headers }
+
+Lorsque vous utilisez un proxy pour gérer HTTPS, votre **serveur d'application** (par exemple Uvicorn via FastAPI CLI) ne connaßt rien du processus HTTPS, il communique en HTTP en clair avec le **Proxy de terminaison TLS**.
+
+Ce **proxy** dĂ©finirait normalement certains en-tĂȘtes HTTP Ă la volĂ©e avant de transmettre la requĂȘte au **serveur d'application**, pour informer le serveur d'application que la requĂȘte est **transmise** par le proxy.
+
+/// note | Détails techniques
+
+Les en-tĂȘtes du proxy sont :
+
+* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
+* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
+* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
+
+///
+
+NĂ©anmoins, comme le **serveur d'application** ne sait pas qu'il se trouve derriĂšre un **proxy** de confiance, par dĂ©faut, il ne ferait pas confiance Ă ces en-tĂȘtes.
+
+Mais vous pouvez configurer le **serveur d'application** pour qu'il fasse confiance aux en-tĂȘtes transmis (*forwarded*) envoyĂ©s par le **proxy**. Si vous utilisez FastAPI CLI, vous pouvez utiliser l'*option CLI* `--forwarded-allow-ips` pour lui indiquer Ă partir de quelles IP il doit faire confiance Ă ces en-tĂȘtes transmis.
+
+Par exemple, si le **serveur d'application** ne reçoit des communications que du **proxy** de confiance, vous pouvez dĂ©finir `--forwarded-allow-ips="*"` pour lui faire faire confiance Ă toutes les IP entrantes, puisqu'il ne recevra des requĂȘtes que depuis l'IP utilisĂ©e par le **proxy**.
+
+De cette façon, l'application sera en mesure de savoir quelle est sa propre URL publique, si elle utilise HTTPS, le domaine, etc.
+
+Cela serait utile, par exemple, pour gérer correctement les redirections.
+
+/// tip | Astuce
+
+Vous pouvez en savoir plus dans la documentation [DerriĂšre un proxy - Activer les en-tĂȘtes transmis par le proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank}
+
+///
+
+## Récapitulatif { #recap }
+
+Disposer de **HTTPS** est trÚs important, et assez **critique** dans la plupart des cas. La majeure partie de l'effort que vous, en tant que développeur, devez fournir autour de HTTPS consiste simplement à **comprendre ces concepts** et leur fonctionnement.
+
+Mais une fois que vous connaissez les informations de base sur **HTTPS pour les développeurs**, vous pouvez facilement combiner et configurer différents outils pour vous aider à tout gérer simplement.
+
+Dans certains des prochains chapitres, je vous montrerai plusieurs exemples concrets de configuration de **HTTPS** pour des applications **FastAPI**. đ
-# Déploiement
+# Déploiement { #deployment }
Le déploiement d'une application **FastAPI** est relativement simple.
-## Que signifie le déploiement
+## Que signifie le déploiement { #what-does-deployment-mean }
**Déployer** une application signifie effectuer les étapes nécessaires pour la rendre **disponible pour les
utilisateurs**.
Ceci contraste avec les Ă©tapes de **dĂ©veloppement**, oĂč vous ĂȘtes constamment en train de modifier le code, de le casser
et de le rĂ©parer, d'arrĂȘter et de redĂ©marrer le serveur de dĂ©veloppement, _etc._
-## Stratégies de déploiement
+## Stratégies de déploiement { #deployment-strategies }
Il existe plusieurs façons de procéder, en fonction de votre cas d'utilisation spécifique et des outils que vous
utilisez.
Vous pouvez **dĂ©ployer un serveur** vous-mĂȘme en utilisant une combinaison d'outils, vous pouvez utiliser un **service
cloud** qui fait une partie du travail pour vous, ou encore d'autres options possibles.
+Par exemple, nous, l'Ă©quipe derriĂšre FastAPI, avons créé <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a>, pour rendre le dĂ©ploiement d'applications FastAPI dans le cloud aussi fluide que possible, avec la mĂȘme expĂ©rience dĂ©veloppeur que lorsque vous travaillez avec FastAPI.
+
Je vais vous montrer certains des principaux concepts que vous devriez probablement avoir à l'esprit lors du déploiement
d'une application **FastAPI** (bien que la plupart de ces concepts s'appliquent Ă tout autre type d'application web).
-# Ă propos des versions de FastAPI
+# Ă propos des versions de FastAPI { #about-fastapi-versions }
-**FastAPI** est déjà utilisé en production dans de nombreuses applications et systÚmes. Et la couverture de test est maintenue à 100 %. Mais son développement est toujours aussi rapide.
+**FastAPI** est déjà utilisé en production dans de nombreuses applications et de nombreux systÚmes. Et la couverture de tests est maintenue à 100 %. Mais son développement avance toujours rapidement.
-De nouvelles fonctionnalités sont ajoutées fréquemment, des bogues sont corrigés réguliÚrement et le code est
-amélioré continuellement.
+De nouvelles fonctionnalités sont ajoutées fréquemment, des bogues sont corrigés réguliÚrement et le code s'améliore continuellement.
-C'est pourquoi les versions actuelles sont toujours `0.x.x`, cela reflĂšte que chaque version peut potentiellement
-recevoir des changements non rétrocompatibles. Cela suit les conventions de <a href="https://semver.org/" class="external-link"
-target="_blank">versionnage sémantique</a>.
+C'est pourquoi les versions actuelles sont toujours `0.x.x`, cela reflÚte que chaque version pourrait potentiellement comporter des changements non rétrocompatibles. Cela suit les conventions de <a href="https://semver.org/" class="external-link" target="_blank">versionnage sémantique</a>.
Vous pouvez créer des applications de production avec **FastAPI** dÚs maintenant (et vous le faites probablement depuis un certain temps), vous devez juste vous assurer que vous utilisez une version qui fonctionne correctement avec le reste de votre code.
-## Ăpinglez votre version de `fastapi`
+## Ăpingler votre version de `fastapi` { #pin-your-fastapi-version }
-Tout d'abord il faut "épingler" la version de **FastAPI** que vous utilisez à la derniÚre version dont vous savez
-qu'elle fonctionne correctement pour votre application.
+La premiĂšre chose que vous devez faire est « Ă©pingler » la version de **FastAPI** que vous utilisez Ă la derniĂšre version spĂ©cifique dont vous savez quâelle fonctionne correctement pour votre application.
-Par exemple, disons que vous utilisez la version `0.45.0` dans votre application.
+Par exemple, disons que vous utilisez la version `0.112.0` dans votre application.
-Si vous utilisez un fichier `requirements.txt`, vous pouvez spécifier la version avec :
+Si vous utilisez un fichier `requirements.txt`, vous pouvez spécifier la version avec :
```txt
-fastapi==0.45.0
+fastapi[standard]==0.112.0
```
-ce qui signifierait que vous utiliseriez exactement la version `0.45.0`.
+ce qui signifierait que vous utiliseriez exactement la version `0.112.0`.
-Ou vous pourriez aussi l'épingler avec :
+Ou vous pourriez aussi l'épingler avec :
```txt
-fastapi>=0.45.0,<0.46.0
+fastapi[standard]>=0.112.0,<0.113.0
```
-cela signifierait que vous utiliseriez les versions `0.45.0` ou supérieures, mais inférieures à `0.46.0`, par exemple, une version `0.45.2` serait toujours acceptée.
+cela signifierait que vous utiliseriez les versions `0.112.0` ou supérieures, mais inférieures à `0.113.0`, par exemple, une version `0.112.2` serait toujours acceptée.
-Si vous utilisez un autre outil pour gérer vos installations, comme Poetry, Pipenv, ou autres, ils ont tous un moyen que vous pouvez utiliser pour définir des versions spécifiques pour vos paquets.
+Si vous utilisez un autre outil pour gérer vos installations, comme `uv`, Poetry, Pipenv, ou autres, ils ont tous un moyen que vous pouvez utiliser pour définir des versions spécifiques pour vos paquets.
-## Versions disponibles
+## Versions disponibles { #available-versions }
Vous pouvez consulter les versions disponibles (par exemple, pour vérifier quelle est la derniÚre version en date) dans les [Notes de version](../release-notes.md){.internal-link target=_blank}.
-## Ă propos des versions
+## Ă propos des versions { #about-versions }
-Suivant les conventions de versionnage sémantique, toute version inférieure à `1.0.0` peut potentiellement ajouter
-des changements non rétrocompatibles.
+Suivant les conventions de versionnage sémantique, toute version inférieure à `1.0.0` peut potentiellement ajouter des changements non rétrocompatibles.
-FastAPI suit également la convention que tout changement de version "PATCH" est pour des corrections de bogues et
-des changements rétrocompatibles.
+FastAPI suit également la convention selon laquelle tout changement de version « PATCH » concerne des corrections de bogues et des changements rétrocompatibles.
/// tip | Astuce
-Le "PATCH" est le dernier chiffre, par exemple, dans `0.2.3`, la version PATCH est `3`.
+Le « PATCH » est le dernier chiffre, par exemple, dans `0.2.3`, la version PATCH est `3`.
///
-Donc, vous devriez ĂȘtre capable d'Ă©pingler une version comme suit :
+Donc, vous devriez ĂȘtre en mesure d'Ă©pingler une version comme suit :
```txt
fastapi>=0.45.0,<0.46.0
```
-Les changements non rétrocompatibles et les nouvelles fonctionnalités sont ajoutés dans les versions "MINOR".
+Les changements non rétrocompatibles et les nouvelles fonctionnalités sont ajoutés dans les versions « MINOR ».
/// tip | Astuce
-Le "MINOR" est le numéro au milieu, par exemple, dans `0.2.3`, la version MINOR est `2`.
+Le « MINOR » est le numéro au milieu, par exemple, dans `0.2.3`, la version MINOR est `2`.
///
-## Mise Ă jour des versions FastAPI
+## Mettre Ă niveau les versions de FastAPI { #upgrading-the-fastapi-versions }
-Vous devriez tester votre application.
+Vous devez ajouter des tests pour votre application.
-Avec **FastAPI** c'est trĂšs facile (merci Ă Starlette), consultez la documentation : [Testing](../tutorial/testing.md){.internal-link target=_blank}
+Avec **FastAPI** c'est trĂšs facile (merci Ă Starlette), consultez les documents : [Tests](../tutorial/testing.md){.internal-link target=_blank}
-AprÚs avoir effectué des tests, vous pouvez mettre à jour la version **FastAPI** vers une version plus récente, et vous assurer que tout votre code fonctionne correctement en exécutant vos tests.
+AprÚs avoir des tests, vous pouvez mettre à niveau la version de **FastAPI** vers une version plus récente et vous assurer que tout votre code fonctionne correctement en exécutant vos tests.
-Si tout fonctionne, ou aprÚs avoir fait les changements nécessaires, et que tous vos tests passent, vous pouvez
-épingler votre version de `fastapi` à cette nouvelle version récente.
+Si tout fonctionne, ou aprÚs avoir effectué les changements nécessaires, et que tous vos tests passent, vous pouvez alors épingler votre `fastapi` à cette nouvelle version récente.
-## Ă propos de Starlette
+## Ă propos de Starlette { #about-starlette }
-Vous ne devriez pas épingler la version de `starlette`.
+Vous ne devez pas épingler la version de `starlette`.
Différentes versions de **FastAPI** utiliseront une version spécifique plus récente de Starlette.
Ainsi, vous pouvez simplement laisser **FastAPI** utiliser la bonne version de Starlette.
-## Ă propos de Pydantic
+## Ă propos de Pydantic { #about-pydantic }
-Pydantic inclut des tests pour **FastAPI** avec ses propres tests, ainsi les nouvelles versions de Pydantic (au-dessus
-de `1.0.0`) sont toujours compatibles avec **FastAPI**.
+Pydantic inclut les tests pour **FastAPI** avec ses propres tests, ainsi les nouvelles versions de Pydantic (au-dessus de `1.0.0`) sont toujours compatibles avec FastAPI.
-Vous pouvez épingler Pydantic à toute version supérieure à `1.0.0` qui fonctionne pour vous et inférieure à `2.0.0`.
+Vous pouvez épingler Pydantic à toute version supérieure à `1.0.0` qui fonctionne pour vous.
-Par exemple :
+Par exemple :
```txt
-pydantic>=1.2.0,<2.0.0
+pydantic>=2.7.0,<3.0.0
```
-# FastAPI
+# FastAPI { #fastapi }
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
- <a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
+ <a href="https://fastapi.tiangolo.com/fr"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>Framework FastAPI, haute performance, facile Ă apprendre, rapide Ă coder, prĂȘt pour la production</em>
---
-**Documentation** : <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
+**Documentation** : <a href="https://fastapi.tiangolo.com/fr" target="_blank">https://fastapi.tiangolo.com/fr</a>
**Code Source** : <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
Les principales fonctionnalités sont :
-* **Rapidité** : De trÚs hautes performances, au niveau de **NodeJS** et **Go** (grùce à Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance).
-* **Rapide à coder** : Augmente la vitesse de développement des fonctionnalités d'environ 200 % à 300 %. *
-* **Moins de bugs** : Réduit d'environ 40 % les erreurs induites par le développeur. *
-* **Intuitif** : Excellente compatibilité avec les IDE. <abbr title="également connu sous le nom d'auto-complétion, autocomplétion, IntelliSense">Complétion</abbr> complÚte. Moins de temps passé à déboguer.
-* **Facile** : Conçu pour ĂȘtre facile Ă utiliser et Ă apprendre. Moins de temps passĂ© Ă lire la documentation.
-* **Concis** : Diminue la duplication de code. De nombreuses fonctionnalités liées à la déclaration de chaque paramÚtre. Moins de bugs.
-* **Robuste** : Obtenez un code prĂȘt pour la production. Avec une documentation interactive automatique.
-* **Basé sur des normes** : Basé sur (et entiÚrement compatible avec) les standards ouverts pour les APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (précédemment connu sous le nom de Swagger) et <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
+* **Rapide** : trĂšs hautes performances, au niveau de **NodeJS** et **Go** (grĂące Ă Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance).
+* **Rapide à coder** : augmente la vitesse de développement des fonctionnalités d'environ 200 % à 300 %. *
+* **Moins de bugs** : réduit d'environ 40 % les erreurs induites par le développeur. *
+* **Intuitif** : excellente compatibilité avec les éditeurs. <abbr title="également appelé autocomplétion, IntelliSense">Autocomplétion</abbr> partout. Moins de temps passé à déboguer.
+* **Facile** : conçu pour ĂȘtre facile Ă utiliser et Ă apprendre. Moins de temps passĂ© Ă lire les documents.
+* **Concis** : diminue la duplication de code. Plusieurs fonctionnalités à partir de chaque déclaration de paramÚtre. Moins de bugs.
+* **Robuste** : obtenez un code prĂȘt pour la production. Avec une documentation interactive automatique.
+* **Basé sur des normes** : basé sur (et entiÚrement compatible avec) les standards ouverts pour les APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (précédemment connu sous le nom de Swagger) et <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation basée sur des tests d'une équipe de développement interne, construisant des applications de production.</small>
-## Sponsors
+## Sponsors { #sponsors }
<!-- sponsors -->
-{% if sponsors %}
+### Sponsor clé de voûte { #keystone-sponsor }
+
+{% for sponsor in sponsors.keystone -%}
+<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
+{% endfor -%}
+
+### Sponsors Or et Argent { #gold-and-silver-sponsors }
+
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
-{% endif %}
<!-- /sponsors -->
-<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
+<a href="https://fastapi.tiangolo.com/fr/fastapi-people/#sponsors" class="external-link" target="_blank">Autres sponsors</a>
-## Opinions
+## Opinions { #opinions }
-"_[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prévois de l'utiliser dans mon équipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux seront intégrés dans le coeur de **Windows** et dans certains produits **Office**._"
+« _[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prĂ©vois de l'utiliser dans mon Ă©quipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux sont intĂ©grĂ©s au cĆur de **Windows** et Ă certains produits **Office**._ »
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
-"_Nous avons adoptĂ© la bibliothĂšque **FastAPI** pour crĂ©er un serveur **REST** qui peut ĂȘtre interrogĂ© pour obtenir des **prĂ©dictions**. [pour Ludwig]_"
+« _Nous avons adoptĂ© la bibliothĂšque **FastAPI** pour crĂ©er un serveur **REST** qui peut ĂȘtre interrogĂ© pour obtenir des **prĂ©dictions**. [pour Ludwig]_ »
-<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin et Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, et Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
-"_**Netflix** a le plaisir d'annoncer la sortie en open-source de notre framework d'orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_"
+« _**Netflix** est heureux d'annoncer la publication en open source de notre framework d'orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_ »
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
-"_Je suis trĂšs enthousiaste Ă propos de **FastAPI**. C'est un bonheur !_"
+« _Je suis plus qu'enthousiaste à propos de **FastAPI**. C'est tellement fun !_ »
-<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong>Auteur du podcast <a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a></strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong>Animateur du podcast <a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a></strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
-"_HonnĂȘtement, ce que vous avez construit a l'air super solide et Ă©lĂ©gant. A bien des Ă©gards, c'est comme ça que je voulais que **Hug** soit - c'est vraiment inspirant de voir quelqu'un construire ça._"
+« _HonnĂȘtement, ce que vous avez construit a l'air super solide et soignĂ©. Ă bien des Ă©gards, c'est ce que je voulais que **Hug** soit â c'est vraiment inspirant de voir quelqu'un construire ça._ »
-<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong> Créateur de <a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>Créateur de <a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
-"_Si vous cherchez à apprendre un **framework moderne** pour créer des APIs REST, regardez **FastAPI** [...] C'est rapide, facile à utiliser et à apprendre [...]_"
+« _Si vous cherchez à apprendre un **framework moderne** pour créer des APIs REST, regardez **FastAPI** [...] C'est rapide, facile à utiliser et facile à apprendre [...]_ »
-"_Nous sommes passés à **FastAPI** pour nos **APIs** [...] Je pense que vous l'aimerez [...]_"
+« _Nous sommes passés à **FastAPI** pour nos **APIs** [...] Je pense que vous l'aimerez [...]_ »
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong>Fondateurs de <a href="https://explosion.ai" target="_blank">Explosion AI</a> - Créateurs de <a href="https://spacy.io" target="_blank">spaCy</a></strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
-"_Si quelqu'un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **bien conçu**, **simple à utiliser** et **trÚs évolutif**. Il est devenu un **composant clé** dans notre stratégie de développement API first et il est à l'origine de nombreux automatismes et services tels que notre ingénieur virtuel TAC._"
+« _Si quelqu'un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conçu**, **simple à utiliser** et **hautement scalable**. Il est devenu un **composant clé** de notre stratégie de développement API-first et alimente de nombreuses automatisations et services tels que notre ingénieur TAC virtuel._ »
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
-## **Typer**, le FastAPI des <abbr title="Command Line Interface">CLI</abbr>
+## Mini documentaire FastAPI { #fastapi-mini-documentary }
+
+Un <a href="https://www.youtube.com/watch?v=mpR8ngthqiE" class="external-link" target="_blank">mini documentaire FastAPI</a> est sorti fin 2025, vous pouvez le regarder en ligne :
+
+<a href="https://www.youtube.com/watch?v=mpR8ngthqiE" target="_blank"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
+
+## **Typer**, le FastAPI des CLIs { #typer-the-fastapi-of-clis }
<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>
-Si vous souhaitez construire une application <abbr title="Command Line Interface">CLI</abbr> utilisable dans un terminal au lieu d'une API web, regardez <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
+Si vous construisez une application <abbr title="Command Line Interface - Interface en ligne de commande">CLI</abbr> Ă utiliser dans un terminal au lieu d'une API web, regardez <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
-**Typer** est le petit frĂšre de FastAPI. Et il est destinĂ© Ă ĂȘtre le **FastAPI des <abbr title="Command Line Interface">CLI</abbr>**. âšïž đ
+**Typer** est le petit frĂšre de FastAPI. Et il est destinĂ© Ă ĂȘtre le **FastAPI des CLIs**. âšïž đ
-## Prérequis
+## Prérequis { #requirements }
FastAPI repose sur les épaules de géants :
* <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> pour les parties web.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> pour les parties données.
-## Installation
-
-<div class="termy">
-
-```console
-$ pip install fastapi
+## Installation { #installation }
----> 100%
-```
-
-</div>
-
-Vous aurez également besoin d'un serveur ASGI pour la production tel que <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a> ou <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
+Créez et activez un <a href="https://fastapi.tiangolo.com/fr/virtual-environments/" class="external-link" target="_blank">environnement virtuel</a> puis installez FastAPI :
<div class="termy">
```console
-$ pip install "uvicorn[standard]"
+$ pip install "fastapi[standard]"
---> 100%
```
</div>
-## Exemple
+**Remarque** : Vous devez vous assurer de mettre « fastapi[standard] » entre guillemets pour garantir que cela fonctionne dans tous les terminaux.
-### Créez
+## Exemple { #example }
-* Créez un fichier `main.py` avec :
+### Créer { #create-it }
-```Python
-from typing import Union
+Créez un fichier `main.py` avec :
+```Python
from fastapi import FastAPI
app = FastAPI()
@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}
```
<details markdown="1">
-<summary>Ou utilisez <code>async def</code> ...</summary>
+<summary>Ou utilisez <code>async def</code>...</summary>
Si votre code utilise `async` / `await`, utilisez `async def` :
-```Python hl_lines="9 14"
-from typing import Union
-
+```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@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}
```
-**Note**
+**Remarque** :
-Si vous n'ĂȘtes pas familier avec cette notion, consultez la section _"Vous ĂȘtes pressĂ©s ?"_ Ă propos de <a href="https://fastapi.tiangolo.com/fr/async/#vous-etes-presses" target="_blank">`async` et `await` dans la documentation</a>.
+Si vous ne savez pas, consultez la section « Vous ĂȘtes pressĂ©s ? » Ă propos de <a href="https://fastapi.tiangolo.com/fr/async/#in-a-hurry" target="_blank">`async` et `await` dans la documentation</a>.
</details>
-### Lancez
+### Lancer { #run-it }
Lancez le serveur avec :
<div class="termy">
```console
-$ uvicorn main:app --reload
-
+$ fastapi dev main.py
+
+ âââââââââââ FastAPI CLI - Development mode ââââââââââââź
+ â â
+ â Serving at: http://127.0.0.1:8000 â
+ â â
+ â API docs: http://127.0.0.1:8000/docs â
+ â â
+ â Running in development mode, for production use: â
+ â â
+ â fastapi run â
+ â â
+ â°ââââââââââââââââââââââââââââââââââââââââââââââââââââââŻ
+
+INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-INFO: Started reloader process [28720]
-INFO: Started server process [28722]
+INFO: Started reloader process [2248755] using WatchFiles
+INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
-<summary>Ă propos de la commande <code>uvicorn main:app --reload</code> ...</summary>
+<summary>Ă propos de la commande <code>fastapi dev main.py</code>...</summary>
-La commande `uvicorn main:app` fait référence à :
+La commande `fastapi dev` lit votre fichier `main.py`, détecte l'application **FastAPI** qu'il contient et lance un serveur avec <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>.
-* `main` : le fichier `main.py` (le "module" Python).
-* `app` : l'objet créé à l'intérieur de `main.py` avec la ligne `app = FastAPI()`.
-* `--reload` : fait redémarrer le serveur aprÚs des changements de code. à n'utiliser que pour le développement.
+Par défaut, `fastapi dev` démarre avec le rechargement automatique activé pour le développement local.
+
+Vous pouvez en savoir plus dans la <a href="https://fastapi.tiangolo.com/fr/fastapi-cli/" target="_blank">documentation de la CLI FastAPI</a>.
</details>
-### Vérifiez
+### Vérifier { #check-it }
Ouvrez votre navigateur Ă l'adresse <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
-Vous obtenez alors cette réponse <abbr title="JavaScript Object Notation">JSON</abbr> :
+Vous verrez la réponse JSON :
```JSON
{"item_id": 5, "q": "somequery"}
```
-Vous venez de créer une API qui :
+Vous avez déjà créé une API qui :
-* Reçoit les requĂȘtes HTTP pour les _chemins_ `/` et `/items/{item_id}`.
-* Les deux _chemins_ acceptent des <em>opérations</em> `GET` (également connu sous le nom de _méthodes_ HTTP).
-* Le _chemin_ `/items/{item_id}` a un _<abbr title="en anglais : path parameter">paramĂštre</abbr>_ `item_id` qui doit ĂȘtre un `int`.
-* Le _chemin_ `/items/{item_id}` a un _<abbr title="en anglais : query param">paramĂštre de requĂȘte</abbr>_ optionnel `q` de type `str`.
+* Reçoit des requĂȘtes HTTP sur les _chemins_ `/` et `/items/{item_id}`.
+* Les deux _chemins_ acceptent des <em>opérations</em> `GET` (également connues sous le nom de _méthodes_ HTTP).
+* Le _chemin_ `/items/{item_id}` a un _paramĂštre de chemin_ `item_id` qui doit ĂȘtre un `int`.
+* Le _chemin_ `/items/{item_id}` a un _paramĂštre de requĂȘte_ optionnel `q` de type `str`.
-### Documentation API interactive
+### Documentation API interactive { #interactive-api-docs }
Maintenant, rendez-vous sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.

-### Documentation API alternative
+### Documentation API alternative { #alternative-api-docs }
Et maintenant, rendez-vous sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
-Vous verrez la documentation interactive automatique de l'API (fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :
+Vous verrez la documentation alternative automatique (fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :

-## Exemple plus poussé
-
-Maintenant, modifiez le fichier `main.py` pour recevoir <abbr title="en anglais : body">le corps</abbr> d'une requĂȘte `PUT`.
+## Mettre Ă niveau l'exemple { #example-upgrade }
-Déclarez ce corps en utilisant les types Python standards, grùce à Pydantic.
+Modifiez maintenant le fichier `main.py` pour recevoir un corps depuis une requĂȘte `PUT`.
-```Python hl_lines="4 9-12 25-27"
-from typing import Union
+Déclarez le corps en utilisant les types Python standard, grùce à Pydantic.
+```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: Union[bool, None] = None
+ is_offer: bool | None = None
@app.get("/")
@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}
return {"item_name": item.name, "item_id": item_id}
```
-Le serveur se recharge normalement automatiquement (car vous avez pensé à `--reload` dans la commande `uvicorn` ci-dessus).
+Le serveur `fastapi dev` devrait se recharger automatiquement.
-### Plus loin avec la documentation API interactive
+### Mettre Ă niveau la documentation API interactive { #interactive-api-docs-upgrade }
Maintenant, rendez-vous sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
-* La documentation interactive de l'API sera automatiquement mise Ă jour, y compris le nouveau corps de la requĂȘte :
+* La documentation interactive de l'API sera automatiquement mise Ă jour, y compris le nouveau corps :

-* Cliquez sur le bouton "Try it out", il vous permet de renseigner les paramĂštres et d'interagir directement avec l'API :
+* Cliquez sur le bouton « Try it out », il vous permet de renseigner les paramÚtres et d'interagir directement avec l'API :

-* Cliquez ensuite sur le bouton "Execute", l'interface utilisateur communiquera avec votre API, enverra les paramÚtres, obtiendra les résultats et les affichera à l'écran :
+* Cliquez ensuite sur le bouton « Execute », l'interface utilisateur communiquera avec votre API, enverra les paramÚtres, obtiendra les résultats et les affichera à l'écran :

-### Plus loin avec la documentation API alternative
+### Mettre Ă niveau la documentation API alternative { #alternative-api-docs-upgrade }
Et maintenant, rendez-vous sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
-* La documentation alternative reflĂ©tera Ă©galement le nouveau paramĂštre de requĂȘte et le nouveau corps :
+* La documentation alternative reflĂštera Ă©galement le nouveau paramĂštre de requĂȘte et le nouveau corps :

-### En résumé
+### En résumé { #recap }
-En rĂ©sumĂ©, vous dĂ©clarez **une fois** les types de paramĂštres, <abbr title="en anglais : body">le corps</abbr> de la requĂȘte, etc. en tant que paramĂštres de fonction.
+En résumé, vous déclarez **une fois** les types de paramÚtres, le corps, etc. en tant que paramÚtres de fonction.
Vous faites cela avec les types Python standard modernes.
Juste du **Python** standard.
-Par exemple, pour un `int`:
+Par exemple, pour un `int` :
```Python
item_id: int
... et avec cette déclaration unique, vous obtenez :
-* Une assistance dans votre IDE, notamment :
- * la complétion.
+* Une assistance dans l'éditeur, notamment :
+ * l'autocomplétion.
* la vérification des types.
* La validation des données :
* des erreurs automatiques et claires lorsque les données ne sont pas valides.
- * une validation mĂȘme pour les objets <abbr title="JavaScript Object Notation">JSON</abbr> profondĂ©ment imbriquĂ©s.
-* <abbr title="aussi connu sous le nom de : serialization, parsing, marshalling">Une conversion</abbr> des données d'entrée : venant du réseau et allant vers les données et types de Python, permettant de lire :
- * le <abbr title="JavaScript Object Notation">JSON</abbr>.
- * <abbr title="en anglais : path parameters">les paramĂštres du chemin</abbr>.
- * <abbr title="en anglais : query parameters">les paramĂštres de la requĂȘte</abbr>.
- * les cookies.
- * <abbr title="en anglais : headers">les en-tĂȘtes</abbr>.
- * <abbr title="en anglais : forms">les formulaires</abbr>.
- * <abbr title="en anglais : files">les fichiers</abbr>.
-* <abbr title="aussi connu sous le nom de : serialization, parsing, marshalling">La conversion</abbr> des données de sortie : conversion des données et types Python en données réseau (au format <abbr title="JavaScript Object Notation">JSON</abbr>), permettant de convertir :
- * les types Python (`str`, `int`, `float`, `bool`, `list`, etc).
- * les objets `datetime`.
- * les objets `UUID`.
- * les modÚles de base de données.
- * ... et beaucoup plus.
-* La documentation API interactive automatique, avec 2 interfaces utilisateur au choix :
+ * une validation mĂȘme pour les objets JSON profondĂ©ment imbriquĂ©s.
+* <abbr title="aussi connu sous le nom de : serialization, parsing, marshalling">Conversion</abbr> des données d'entrée : venant du réseau vers les données et types Python. Lecture depuis :
+ * JSON.
+ * ParamĂštres de chemin.
+ * ParamĂštres de requĂȘte.
+ * Cookies.
+ * En-tĂȘtes.
+ * Formulaires.
+ * Fichiers.
+* <abbr title="aussi connu sous le nom de : serialization, parsing, marshalling">Conversion</abbr> des données de sortie : conversion des données et types Python en données réseau (au format JSON) :
+ * Conversion des types Python (`str`, `int`, `float`, `bool`, `list`, etc).
+ * Objets `datetime`.
+ * Objets `UUID`.
+ * ModÚles de base de données.
+ * ... et bien plus.
+* Documentation API interactive automatique, avec 2 interfaces utilisateur au choix :
* Swagger UI.
* ReDoc.
---
-Pour revenir à l'exemple de code précédent, **FastAPI** permet de :
+Pour revenir à l'exemple de code précédent, **FastAPI** va :
-* Valider que `item_id` existe dans le chemin des requĂȘtes `GET` et `PUT`.
+* Valider la prĂ©sence d'un `item_id` dans le chemin pour les requĂȘtes `GET` et `PUT`.
* Valider que `item_id` est de type `int` pour les requĂȘtes `GET` et `PUT`.
- * Si ce n'est pas le cas, le client voit une erreur utile et claire.
-* VĂ©rifier qu'il existe un paramĂštre de requĂȘte facultatif nommĂ© `q` (comme dans `http://127.0.0.1:8000/items/foo?q=somequery`) pour les requĂȘtes `GET`.
- * Puisque le paramÚtre `q` est déclaré avec `= None`, il est facultatif.
- * Sans le `None`, il serait nĂ©cessaire (comme l'est <abbr title="en anglais : body">le corps</abbr> de la requĂȘte dans le cas du `PUT`).
-* Pour les requĂȘtes `PUT` vers `/items/{item_id}`, de lire <abbr title="en anglais : body">le corps</abbr> en <abbr title="JavaScript Object Notation">JSON</abbr> :
- * VĂ©rifier qu'il a un attribut obligatoire `name` qui devrait ĂȘtre un `str`.
- * VĂ©rifier qu'il a un attribut obligatoire `prix` qui doit ĂȘtre un `float`.
- * VĂ©rifier qu'il a un attribut facultatif `is_offer`, qui devrait ĂȘtre un `bool`, s'il est prĂ©sent.
- * Tout cela fonctionnerait également pour les objets <abbr title="JavaScript Object Notation">JSON</abbr> profondément imbriqués.
-* Convertir de et vers <abbr title="JavaScript Object Notation">JSON</abbr> automatiquement.
-* Documenter tout avec OpenAPI, qui peut ĂȘtre utilisĂ© par :
- * Les systĂšmes de documentation interactifs.
- * Les systÚmes de génération automatique de code client, pour de nombreuses langues.
+ * Si ce n'est pas le cas, le client verra une erreur utile et claire.
+* VĂ©rifier s'il existe un paramĂštre de requĂȘte optionnel nommĂ© `q` (comme dans `http://127.0.0.1:8000/items/foo?q=somequery`) pour les requĂȘtes `GET`.
+ * Comme le paramÚtre `q` est déclaré avec `= None`, il est optionnel.
+ * Sans le `None`, il serait requis (comme l'est le corps dans le cas de `PUT`).
+* Pour les requĂȘtes `PUT` vers `/items/{item_id}`, lire le corps au format JSON :
+ * VĂ©rifier qu'il a un attribut obligatoire `name` qui doit ĂȘtre un `str`.
+ * VĂ©rifier qu'il a un attribut obligatoire `price` qui doit ĂȘtre un `float`.
+ * VĂ©rifier qu'il a un attribut optionnel `is_offer`, qui doit ĂȘtre un `bool`, s'il est prĂ©sent.
+ * Tout cela fonctionne également pour les objets JSON profondément imbriqués.
+* Convertir automatiquement depuis et vers JSON.
+* Tout documenter avec OpenAPI, qui peut ĂȘtre utilisĂ© par :
+ * des systĂšmes de documentation interactive.
+ * des systÚmes de génération automatique de clients, pour de nombreux langages.
* Fournir directement 2 interfaces web de documentation interactive.
---
-Nous n'avons fait qu'effleurer la surface, mais vous avez déjà une idée de la façon dont tout cela fonctionne.
+Nous n'avons fait qu'effleurer la surface, mais vous avez déjà une idée de la façon dont tout fonctionne.
Essayez de changer la ligne contenant :
... "item_name": item.name ...
```
-... vers :
+... Ă :
```Python
... "item_price": item.price ...
```
-... et voyez comment votre Ă©diteur complĂ©tera automatiquement les attributs et connaĂÂźtra leurs types :
+... et voyez comment votre Ă©diteur complĂšte automatiquement les attributs et connaĂÂźt leurs types :
-
+
Pour un exemple plus complet comprenant plus de fonctionnalités, voir le <a href="https://fastapi.tiangolo.com/fr/tutorial/">Tutoriel - Guide utilisateur</a>.
-**Spoiler alert** : le tutoriel - guide utilisateur inclut :
+**Alerte spoiler** : le tutoriel - guide utilisateur inclut :
-* DĂ©claration de **paramĂštres** provenant d'autres endroits diffĂ©rents comme : **<abbr title="en anglais : headers">en-tĂȘtes</abbr>.**, **cookies**, **champs de formulaire** et **fichiers**.
-* L'utilisation de **contraintes de validation** comme `maximum_length` ou `regex`.
-* Un **<abbr title="aussi connu sous le nom de composants, ressources, fournisseurs, services, injectables">systÚme d'injection de dépendance </abbr>** trÚs puissant et facile à utiliser .
-* Sécurité et authentification, y compris la prise en charge de **OAuth2** avec les **<abbr title="en anglais : JWT tokens">jetons <abbr title="JSON Web Tokens">JWT</abbr></abbr>** et l'authentification **HTTP Basic**.
-* Des techniques plus avancées (mais tout aussi faciles) pour déclarer les **modÚles <abbr title="JavaScript Object Notation">JSON</abbr> profondément imbriqués** (grùce à Pydantic).
-* Intégration de **GraphQL** avec <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> et d'autres bibliothÚques.
-* D'obtenir de nombreuses fonctionnalités supplémentaires (grùce à Starlette) comme :
+* DĂ©claration de **paramĂštres** provenant d'autres emplacements comme : **en-tĂȘtes**, **cookies**, **champs de formulaire** et **fichiers**.
+* Comment définir des **contraintes de validation** comme `maximum_length` ou `regex`.
+* Un systÚme **<abbr title="aussi connu sous le nom de composants, ressources, fournisseurs, services, injectables">d'injection de dépendances</abbr>** trÚs puissant et facile à utiliser.
+* Sécurité et authentification, y compris la prise en charge de **OAuth2** avec des **JWT tokens** et l'authentification **HTTP Basic**.
+* Des techniques plus avancées (mais tout aussi faciles) pour déclarer des **modÚles JSON profondément imbriqués** (grùce à Pydantic).
+* Intégration **GraphQL** avec <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> et d'autres bibliothÚques.
+* De nombreuses fonctionnalités supplémentaires (grùce à Starlette) comme :
* **WebSockets**
- * de tester le code trĂšs facilement avec `requests` et `pytest`
- * **<abbr title="Cross-Origin Resource Sharing">CORS</abbr>**
+ * des tests extrĂȘmement faciles basĂ©s sur HTTPX et `pytest`
+ * **CORS**
* **Cookie Sessions**
* ... et plus encore.
-## Performance
+### Déployer votre application (optionnel) { #deploy-your-app-optional }
-Les benchmarks TechEmpower indépendants montrent que les applications **FastAPI** s'exécutant sous Uvicorn sont <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"> parmi les frameworks existants en Python les plus rapides </a>, juste derriÚre Starlette et Uvicorn (utilisés en interne par FastAPI). (*)
+Vous pouvez, si vous le souhaitez, dĂ©ployer votre application FastAPI sur <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, allez vous inscrire sur la liste d'attente si ce n'est pas dĂ©jĂ fait. đ
+
+Si vous avez dĂ©jĂ un compte **FastAPI Cloud** (nous vous avons invitĂ© depuis la liste d'attente đ), vous pouvez dĂ©ployer votre application avec une seule commande.
+
+Avant de dĂ©ployer, assurez-vous d'ĂȘtre connectĂ© :
+
+<div class="termy">
+
+```console
+$ fastapi login
+
+You are logged in to FastAPI Cloud đ
+```
+
+</div>
+
+Puis déployez votre application :
+
+<div class="termy">
+
+```console
+$ fastapi deploy
+
+Deploying to FastAPI Cloud...
+
+â
Deployment successful!
+
+đ Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
+```
+
+</div>
+
+C'est tout ! Vous pouvez maintenant accĂ©der Ă votre application Ă cette URL. âš
+
+#### Ă propos de FastAPI Cloud { #about-fastapi-cloud }
+
+**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** est construit par le mĂȘme auteur et la mĂȘme Ă©quipe derriĂšre **FastAPI**.
+
+Il simplifie le processus de **construction**, de **déploiement** et **d'accÚs** à une API avec un effort minimal.
+
+Il apporte la mĂȘme **expĂ©rience dĂ©veloppeur** de la crĂ©ation d'applications avec FastAPI au **dĂ©ploiement** dans le cloud. đ
+
+FastAPI Cloud est le principal sponsor et financeur des projets open source *FastAPI and friends*. âš
+
+#### Déployer sur d'autres fournisseurs cloud { #deploy-to-other-cloud-providers }
+
+FastAPI est open source et basé sur des standards. Vous pouvez déployer des applications FastAPI sur n'importe quel fournisseur cloud de votre choix.
+
+Suivez les guides de votre fournisseur cloud pour y dĂ©ployer des applications FastAPI. đ€
+
+## Performance { #performance }
+
+Les benchmarks TechEmpower indĂ©pendants montrent que les applications **FastAPI** s'exĂ©cutant sous Uvicorn sont <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">parmi les frameworks Python les plus rapides</a>, juste derriĂšre Starlette et Uvicorn eux-mĂȘmes (utilisĂ©s en interne par FastAPI). (*)
Pour en savoir plus, consultez la section <a href="https://fastapi.tiangolo.com/fr/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
-## Dépendances facultatives
+## Dépendances { #dependencies }
+
+FastAPI dépend de Pydantic et Starlette.
+
+### Dépendances `standard` { #standard-dependencies }
-Utilisées par Pydantic:
+Lorsque vous installez FastAPI avec `pip install "fastapi[standard]"`, il inclut le groupe `standard` de dépendances optionnelles :
-* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - pour la validation des adresses email.
+Utilisées par Pydantic :
+
+* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - pour la validation des adresses e-mail.
Utilisées par Starlette :
-* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Obligatoire si vous souhaitez utiliser `TestClient`.
+* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Obligatoire si vous souhaitez utiliser le `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obligatoire si vous souhaitez utiliser la configuration de template par défaut.
-* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obligatoire si vous souhaitez supporter le <abbr title="convertit la chaine de caractĂšre d'une requĂȘte HTTP en donnĂ©e Python">"dĂ©codage"</abbr> de formulaire avec `request.form()`.
-* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Obligatoire pour la prise en charge de `SessionMiddleware`.
-* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Obligatoire pour le support `SchemaGenerator` de Starlette (vous n'en avez probablement pas besoin avec FastAPI).
+* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obligatoire si vous souhaitez prendre en charge lâ<abbr title="convertir la chaĂźne issue d'une requĂȘte HTTP en donnĂ©es Python">« parsing »</abbr> de formulaires avec `request.form()`.
-Utilisées par FastAPI / Starlette :
+Utilisées par FastAPI :
-* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - Pour le serveur qui charge et sert votre application.
-* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Obligatoire si vous voulez utiliser `ORJSONResponse`.
-* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Obligatoire si vous souhaitez utiliser `UJSONResponse`.
+* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - pour le serveur qui charge et sert votre application. Cela inclut `uvicorn[standard]`, qui comprend certaines dépendances (par ex. `uvloop`) nécessaires pour une haute performance.
+* `fastapi-cli[standard]` - pour fournir la commande `fastapi`.
+ * Cela inclut `fastapi-cloud-cli`, qui vous permet de déployer votre application FastAPI sur <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
+
+### Sans les dépendances `standard` { #without-standard-dependencies }
+
+Si vous ne souhaitez pas inclure les dépendances optionnelles `standard`, vous pouvez installer avec `pip install fastapi` au lieu de `pip install "fastapi[standard]"`.
-Vous pouvez tout installer avec `pip install fastapi[all]`.
+### Sans `fastapi-cloud-cli` { #without-fastapi-cloud-cli }
+
+Si vous souhaitez installer FastAPI avec les dépendances standard mais sans `fastapi-cloud-cli`, vous pouvez installer avec `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
+
+### Dépendances optionnelles supplémentaires { #additional-optional-dependencies }
+
+Il existe des dépendances supplémentaires que vous pourriez vouloir installer.
+
+Dépendances optionnelles supplémentaires pour Pydantic :
+
+* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - pour la gestion des paramĂštres.
+* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - pour des types supplémentaires à utiliser avec Pydantic.
+
+Dépendances optionnelles supplémentaires pour FastAPI :
+
+* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Obligatoire si vous souhaitez utiliser `ORJSONResponse`.
+* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Obligatoire si vous souhaitez utiliser `UJSONResponse`.
-## Licence
+## Licence { #license }
Ce projet est soumis aux termes de la licence MIT.
-# Apprendre
+# Apprendre { #learn }
Voici les sections introductives et les tutoriels pour apprendre **FastAPI**.
-Vous pouvez considĂ©rer ceci comme un **manuel**, un **cours**, la **mĂ©thode officielle** et recommandĂ©e pour apprĂ©hender FastAPI. đ
+Vous pouvez considĂ©rer ceci comme un **livre**, un **cours**, la **mĂ©thode officielle** et recommandĂ©e pour apprendre FastAPI. đ
-# Génération de projets - ModÚle
-
-Vous pouvez utiliser un générateur de projet pour commencer, qui réalisera pour vous la mise en place de bases cÎté architecture globale, sécurité, base de données et premiÚres routes d'API.
-
-Un générateur de projet fera toujours une mise en place trÚs subjective que vous devriez modifier et adapter suivant vos besoins, mais cela reste un bon point de départ pour vos projets.
-
-## Full Stack FastAPI PostgreSQL
-
-GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-postgresql</a>
-
-### Full Stack FastAPI PostgreSQL - Fonctionnalités
-
-* Intégration **Docker** complÚte (basée sur Docker).
-* Déploiement Docker en mode <a href="https://docs.docker.com/engine/swarm/" class="external-link" target="_blank">Swarm</a>
-* Intégration **Docker Compose** et optimisation pour développement local.
-* Serveur web Python **prĂȘt au dĂ©ploiement** utilisant Uvicorn et Gunicorn.
-* Backend Python <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">**FastAPI**</a> :
- * **Rapide** : TrĂšs hautes performances, comparables Ă **NodeJS** ou **Go** (grĂące Ă Starlette et Pydantic).
- * **Intuitif** : Excellent support des éditeurs. <abbr title="aussi appelée auto-complétion, autocomplétion, IntelliSense...">Complétion</abbr> partout. Moins de temps passé à déboguer.
- * **Facile** : Fait pour ĂȘtre facile Ă utiliser et apprendre. Moins de temps passĂ© Ă lire de la documentation.
- * **Concis** : Minimise la duplication de code. Plusieurs fonctionnalités à chaque déclaration de paramÚtre.
- * **Robuste** : Obtenez du code prĂȘt pour ĂȘtre utilisĂ© en production. Avec de la documentation automatique interactive.
- * **Basé sur des normes** : Basé sur (et totalement compatible avec) les normes ouvertes pour les APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> et <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
- * <a href="https://fastapi.tiangolo.com/features/" class="external-link" target="_blank">**Et bien d'autres fonctionnalités**</a> comme la validation automatique, la sérialisation, l'authentification avec OAuth2 JWT tokens, etc.
-* Hashage de **mots de passe sécurisé** par défaut.
-* Authentification par **jetons JWT**.
-* ModĂšles **SQLAlchemy** (indĂ©pendants des extensions Flask, afin qu'ils puissent ĂȘtre utilisĂ©s directement avec des *workers* Celery).
-* ModÚle de démarrages basiques pour les utilisateurs (à modifier et supprimer au besoin).
-* Migrations **Alembic**.
-* **CORS** (partage des ressources entre origines multiples, ou *Cross Origin Resource Sharing*).
-* *Worker* **Celery** pouvant importer et utiliser les modĂšles et le code du reste du backend.
-* Tests du backend REST basĂ©s sur **Pytest**, intĂ©grĂ©s dans Docker, pour que vous puissiez tester toutes les interactions de l'API indĂ©pendamment de la base de donnĂ©es. Ătant exĂ©cutĂ©s dans Docker, les tests peuvent utiliser un nouvel entrepĂŽt de donnĂ©es créé de zĂ©ro Ă chaque fois (vous pouvez donc utiliser ElasticSearch, MongoDB, CouchDB, etc. et juste tester que l'API fonctionne).
-* Intégration Python facile avec **Jupyter Kernels** pour le développement à distance ou intra-Docker avec des extensions comme Atom Hydrogen ou Visual Studio Code Jupyter.
-* Frontend **Vue** :
- * Généré avec Vue CLI.
- * Gestion de l'**Authentification JWT**.
- * Page de connexion.
- * AprĂšs la connexion, page de tableau de bord principal.
- * Tableau de bord principal avec création et modification d'utilisateurs.
- * Modification de ses propres caractéristiques utilisateur.
- * **Vuex**.
- * **Vue-router**.
- * **Vuetify** pour de magnifiques composants *material design*.
- * **TypeScript**.
- * Serveur Docker basĂ© sur **Nginx** (configurĂ© pour ĂȘtre facilement manipulĂ© avec Vue-router).
- * Utilisation de *Docker multi-stage building*, pour ne pas avoir besoin de sauvegarder ou *commit* du code compilé.
- * Tests frontend exĂ©cutĂ©s Ă la compilation (pouvant ĂȘtre dĂ©sactivĂ©s).
- * Fait aussi modulable que possible, pour pouvoir fonctionner comme tel, tout en pouvant ĂȘtre utilisĂ© qu'en partie grĂące Ă Vue CLI.
-* **PGAdmin** pour les bases de données PostgreSQL, facilement modifiable pour utiliser PHPMYAdmin ou MySQL.
-* **Flower** pour la surveillance de tĂąches Celery.
-* Ăquilibrage de charge entre le frontend et le backend avec **Traefik**, afin de pouvoir avoir les deux sur le mĂȘme domaine, sĂ©parĂ©s par chemins, mais servis par diffĂ©rents conteneurs.
-* Intégration Traefik, comprenant la génération automatique de certificat **HTTPS** Let's Encrypt.
-* GitLab **CI** (intégration continue), comprenant des tests pour le frontend et le backend.
-
-## Full Stack FastAPI Couchbase
-
-GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-couchbase</a>
-
-â ïž **ATTENTION** â ïž
-
-Si vous démarrez un nouveau projet de zéro, allez voir les alternatives au début de cette page.
-
-Par exemple, le gĂ©nĂ©rateur de projet <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">Full Stack FastAPI PostgreSQL</a> peut ĂȘtre une meilleure alternative, Ă©tant activement maintenu et utilisĂ© et comprenant toutes les nouvelles fonctionnalitĂ©s et amĂ©liorations.
-
-Vous ĂȘtes toujours libre d'utiliser le gĂ©nĂ©rateur basĂ© sur Couchbase si vous le voulez, cela devrait probablement fonctionner correctement, et si vous avez dĂ©jĂ un projet gĂ©nĂ©rĂ© en utilisant ce dernier, cela devrait fonctionner aussi (et vous l'avez dĂ©jĂ probablement mis Ă jour suivant vos besoins).
-
-Vous pouvez en apprendre plus dans la documentation du dépÎt GithHub.
-
-## Full Stack FastAPI MongoDB
-
-...viendra surement plus tard, suivant le temps que j'ai. đ
đ
-
-## ModĂšles d'apprentissage automatique avec spaCy et FastAPI
-
-GitHub : <a href="https://github.com/microsoft/cookiecutter-spacy-fastapi" class="external-link" target="_blank">https://github.com/microsoft/cookiecutter-spacy-fastapi</a>
-
-## ModÚles d'apprentissage automatique avec spaCy et FastAPI - Fonctionnalités
-
-* Intégration d'un modÚle NER **spaCy**.
-* Formatage de requĂȘte pour **Azure Cognitive Search**.
-* Serveur Python web **prĂȘt Ă utiliser en production** utilisant Uvicorn et Gunicorn.
-* Déploiement CI/CD Kubernetes pour **Azure DevOps** (AKS).
-* **Multilangues**. Choisissez facilement l'une des langues intégrées à spaCy durant la mise en place du projet.
-* **Facilement généralisable** à d'autres bibliothÚques similaires (Pytorch, Tensorflow), et non juste spaCy.
+# ModĂšle Full Stack FastAPI { #full-stack-fastapi-template }
+
+Les modĂšles, bien qu'ils soient gĂ©nĂ©ralement livrĂ©s avec une configuration spĂ©cifique, sont conçus pour ĂȘtre flexibles et personnalisables. Cela vous permet de les modifier et de les adapter aux exigences de votre projet, ce qui en fait un excellent point de dĂ©part. đ
+
+Vous pouvez utiliser ce modĂšle pour dĂ©marrer, car il inclut une grande partie de la configuration initiale, la sĂ©curitĂ©, la base de donnĂ©es et quelques endpoints d'API dĂ©jĂ prĂȘts pour vous.
+
+DépÎt GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-template" class="external-link" target="_blank">ModÚle Full Stack FastAPI</a>
+
+## ModÚle Full Stack FastAPI - Pile technologique et fonctionnalités { #full-stack-fastapi-template-technology-stack-and-features }
+
+- ⥠[**FastAPI**](https://fastapi.tiangolo.com/fr) pour l'API backend Python.
+ - 𧰠[SQLModel](https://sqlmodel.tiangolo.com) pour les interactions avec la base de données SQL en Python (ORM).
+ - đ [Pydantic](https://docs.pydantic.dev), utilisĂ© par FastAPI, pour la validation des donnĂ©es et la gestion des paramĂštres.
+ - đŸ [PostgreSQL](https://www.postgresql.org) comme base de donnĂ©es SQL.
+- đ [React](https://react.dev) pour le frontend.
+ - đ Utilisation de TypeScript, des hooks, de Vite et d'autres Ă©lĂ©ments d'un stack frontend moderne.
+ - đš [Tailwind CSS](https://tailwindcss.com) et [shadcn/ui](https://ui.shadcn.com) pour les composants frontend.
+ - đ€ Un client frontend gĂ©nĂ©rĂ© automatiquement.
+ - đ§Ș [Playwright](https://playwright.dev) pour les tests de bout en bout.
+ - đŠ Prise en charge du mode sombre.
+- đ [Docker Compose](https://www.docker.com) pour le dĂ©veloppement et la production.
+- đ Hachage sĂ©curisĂ© des mots de passe par dĂ©faut.
+- đ Authentification JWT (JSON Web Token).
+- đ« RĂ©cupĂ©ration de mot de passe par e-mail.
+- â
Tests avec [Pytest](https://pytest.org).
+- đ [Traefik](https://traefik.io) comme proxy inverse / rĂ©partiteur de charge.
+- đą Instructions de dĂ©ploiement avec Docker Compose, y compris la configuration d'un proxy Traefik frontal pour gĂ©rer les certificats HTTPS automatiques.
+- đ CI (intĂ©gration continue) et CD (dĂ©ploiement continu) basĂ©s sur GitHub Actions.
-# Introduction aux Types Python
+# Introduction aux types Python { #python-types-intro }
-Python supporte des annotations de type (ou *type hints*) optionnelles.
+Python prend en charge des « type hints » (aussi appelées « annotations de type ») facultatives.
-Ces annotations de type constituent une syntaxe spéciale qui permet de déclarer le <abbr title="par exemple : str, int, float, bool">type</abbr> d'une variable.
+Ces « type hints » ou annotations sont une syntaxe spéciale qui permet de déclarer le <abbr title="par exemple : str, int, float, bool">type</abbr> d'une variable.
-En déclarant les types de vos variables, cela permet aux différents outils comme les éditeurs de texte d'offrir un meilleur support.
+En déclarant les types de vos variables, les éditeurs et outils peuvent vous offrir un meilleur support.
-Ce chapitre n'est qu'un **tutoriel rapide / rappel** sur les annotations de type Python.
-Seulement le minimum nécessaire pour les utiliser avec **FastAPI** sera couvert... ce qui est en réalité trÚs peu.
+Ceci est un **tutoriel rapide / rappel** à propos des annotations de type Python. Il couvre uniquement le minimum nécessaire pour les utiliser avec **FastAPI** ... ce qui est en réalité trÚs peu.
-**FastAPI** est totalement basé sur ces annotations de type, qui lui donnent de nombreux avantages.
+**FastAPI** est totalement basé sur ces annotations de type, elles lui donnent de nombreux avantages et bénéfices.
-Mais mĂȘme si vous n'utilisez pas ou n'utiliserez jamais **FastAPI**, vous pourriez bĂ©nĂ©ficier d'apprendre quelques choses sur ces derniĂšres.
+Mais mĂȘme si vous n'utilisez jamais **FastAPI**, vous auriez intĂ©rĂȘt Ă en apprendre un peu Ă leur sujet.
-/// note
+/// note | Remarque
-Si vous ĂȘtes un expert Python, et que vous savez dĂ©jĂ **tout** sur les annotations de type, passez au chapitre suivant.
+Si vous ĂȘtes un expert Python, et que vous savez dĂ©jĂ tout sur les annotations de type, passez au chapitre suivant.
///
-## Motivations
+## Motivation { #motivation }
-Prenons un exemple simple :
+Commençons par un exemple simple :
-{*../../docs_src/python_types/tutorial001.py*}
+{* ../../docs_src/python_types/tutorial001_py39.py *}
-Exécuter ce programe affiche :
+Exécuter ce programme affiche :
```
John Doe
```
-La fonction :
+La fonction fait ce qui suit :
* Prend un `first_name` et un `last_name`.
-* Convertit la premiĂšre lettre de chaque paramĂštre en majuscules grĂące Ă `title()`.
-* ConcatÚne les résultats avec un espace entre les deux.
+* Convertit la premiĂšre lettre de chacun en majuscule avec `title()`.
+* <abbr title="Les met ensemble, en un seul. Avec le contenu de l'un aprĂšs l'autre.">ConcatĂšne</abbr> ces deux valeurs avec un espace au milieu.
-{*../../docs_src/python_types/tutorial001.py hl[2] *}
+{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
-### Limitations
+### Modifier le code { #edit-it }
C'est un programme trĂšs simple.
Mais maintenant imaginez que vous l'écriviez de zéro.
-Ă un certain point vous auriez commencĂ© la dĂ©finition de la fonction, vous aviez les paramĂštres prĂȘts.
+Ă un certain moment, vous auriez commencĂ© la dĂ©finition de la fonction, vous aviez les paramĂštres prĂȘts ...
-Mais vous aviez besoin de "cette méthode qui convertit la premiÚre lettre en majuscule".
+Mais ensuite vous devez appeler « cette méthode qui convertit la premiÚre lettre en majuscule ».
-Ătait-ce `upper` ? `uppercase` ? `first_uppercase` ? `capitalize` ?
+Ătait-ce `upper` ? Ătait-ce `uppercase` ? `first_uppercase` ? `capitalize` ?
-Vous essayez donc d'utiliser le vieil ami du programmeur, l'auto-complétion de l'éditeur.
+Vous essayez alors avec l'ami de toujours des programmeurs, l'autocomplétion de l'éditeur.
-Vous écrivez le premier paramÚtre, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour déclencher l'auto-complétion.
+Vous tapez le premier paramÚtre de la fonction, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour déclencher l'autocomplétion.
-Mais malheureusement, rien d'utile n'en résulte :
+Mais, malheureusement, vous n'obtenez rien d'utile :
<img src="/img/python-types/image01.png">
-### Ajouter des types
+### Ajouter des types { #add-types }
Modifions une seule ligne de la version précédente.
-Nous allons changer seulement cet extrait, les paramĂštres de la fonction, de :
-
+Nous allons changer exactement ce fragment, les paramĂštres de la fonction, de :
```Python
first_name, last_name
C'est tout.
-Ce sont des annotations de types :
+Ce sont les « annotations de type » :
-{*../../docs_src/python_types/tutorial002.py hl[1] *}
+{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
-à ne pas confondre avec la déclaration de valeurs par défaut comme ici :
+Ce n'est pas la mĂȘme chose que de dĂ©clarer des valeurs par dĂ©faut, ce qui serait :
```Python
first_name="john", last_name="doe"
```
-C'est une chose différente.
+C'est différent.
-On utilise un deux-points (`:`), et pas un égal (`=`).
+Nous utilisons des deux-points (`:`), pas des signes égal (`=`).
-Et ajouter des annotations de types ne crée normalement pas de différence avec le comportement qui aurait eu lieu si elles n'étaient pas là .
+Et ajouter des annotations de type ne change normalement pas ce qui se passe par rapport Ă ce qui se passerait sans elles.
-Maintenant, imaginez que vous ĂȘtes en train de crĂ©er cette fonction, mais avec des annotations de type cette fois.
+Mais maintenant, imaginez que vous ĂȘtes Ă nouveau en train de crĂ©er cette fonction, mais avec des annotations de type.
-Au mĂȘme moment que durant l'exemple prĂ©cĂ©dent, vous essayez de dĂ©clencher l'auto-complĂ©tion et vous voyez :
+Au mĂȘme moment, vous essayez de dĂ©clencher l'autocomplĂ©tion avec `Ctrl+Espace` et vous voyez :
<img src="/img/python-types/image02.png">
-Vous pouvez donc dérouler les options jusqu'à trouver la méthode à laquelle vous pensiez.
+Avec cela, vous pouvez faire défiler en voyant les options, jusqu'à trouver celle qui « vous dit quelque chose » :
<img src="/img/python-types/image03.png">
-## Plus de motivations
+## Plus de motivation { #more-motivation }
-Cette fonction possÚde déjà des annotations de type :
+Regardez cette fonction, elle a déjà des annotations de type :
-{*../../docs_src/python_types/tutorial003.py hl[1] *}
+{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
-Comme l'éditeur connaßt le type des variables, vous n'avez pas seulement l'auto-complétion, mais aussi de la détection d'erreurs :
+Comme l'éditeur connaßt les types des variables, vous n'obtenez pas seulement l'autocomplétion, vous obtenez aussi des vérifications d'erreurs :
<img src="/img/python-types/image04.png">
-Maintenant que vous avez connaissance du problĂšme, convertissez `age` en <abbr title="string">chaĂźne de caractĂšres</abbr> grĂące Ă `str(age)` :
+Vous savez maintenant qu'il faut corriger, convertir `age` en chaĂźne avec `str(age)` :
-{*../../docs_src/python_types/tutorial004.py hl[2] *}
+{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
-## Déclarer des types
+## Déclarer des types { #declaring-types }
-Vous venez de voir lĂ oĂč les types sont gĂ©nĂ©ralement dĂ©clarĂ©s : dans les paramĂštres de fonctions.
+Vous venez de voir l'endroit principal pour déclarer des annotations de type : dans les paramÚtres des fonctions.
-C'est aussi ici que vous les utiliseriez avec **FastAPI**.
+C'est aussi l'endroit principal oĂč vous les utiliserez avec **FastAPI**.
-### Types simples
+### Types simples { #simple-types }
-Vous pouvez déclarer tous les types de Python, pas seulement `str`.
+Vous pouvez déclarer tous les types standards de Python, pas seulement `str`.
-Comme par exemple :
+Vous pouvez utiliser, par exemple :
* `int`
* `float`
* `bool`
* `bytes`
-{*../../docs_src/python_types/tutorial005.py hl[1] *}
+{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
-### Types génériques avec des paramÚtres de types
+### Types génériques avec paramÚtres de type { #generic-types-with-type-parameters }
-Il existe certaines structures de données qui contiennent d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent elles aussi avoir leurs propres types.
+Il existe certaines structures de données qui peuvent contenir d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent aussi avoir leur propre type.
-Pour déclarer ces types et les types internes, on utilise le module standard de Python `typing`.
+Ces types qui ont des types internes sont appelĂ©s types « gĂ©nĂ©riques ». Et il est possible de les dĂ©clarer, mĂȘme avec leurs types internes.
-Il existe spécialement pour supporter ces annotations de types.
+Pour déclarer ces types et les types internes, vous pouvez utiliser le module standard Python `typing`. Il existe spécifiquement pour prendre en charge ces annotations de type.
-#### `List`
+#### Versions plus récentes de Python { #newer-versions-of-python }
-Par exemple, définissons une variable comme `list` de `str`.
+La syntaxe utilisant `typing` est compatible avec toutes les versions, de Python 3.6 aux plus récentes, y compris Python 3.9, Python 3.10, etc.
-Importez `List` (avec un `L` majuscule) depuis `typing`.
+Au fur et Ă mesure que Python Ă©volue, les versions plus rĂ©centes apportent un meilleur support pour ces annotations de type et dans de nombreux cas vous n'aurez mĂȘme pas besoin d'importer et d'utiliser le module `typing` pour les dĂ©clarer.
-{*../../docs_src/python_types/tutorial006.py hl[1] *}
+Si vous pouvez choisir une version plus récente de Python pour votre projet, vous pourrez profiter de cette simplicité supplémentaire.
-Déclarez la variable, en utilisant la syntaxe des deux-points (`:`).
+Dans toute la documentation, il y a des exemples compatibles avec chaque version de Python (lorsqu'il y a une différence).
-Et comme type, mettez `List`.
+Par exemple « Python 3.6+ » signifie que c'est compatible avec Python 3.6 ou supérieur (y compris 3.7, 3.8, 3.9, 3.10, etc.). Et « Python 3.9+ » signifie que c'est compatible avec Python 3.9 ou supérieur (y compris 3.10, etc).
-Les listes étant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) :
+Si vous pouvez utiliser les derniÚres versions de Python, utilisez les exemples pour la derniÚre version, ils auront la meilleure et la plus simple syntaxe, par exemple, « Python 3.10+ ».
-{*../../docs_src/python_types/tutorial006.py hl[4] *}
+#### Liste { #list }
-/// tip | Astuce
+Par exemple, définissons une variable comme une `list` de `str`.
+
+DĂ©clarez la variable, en utilisant la mĂȘme syntaxe avec deux-points (`:`).
+
+Comme type, mettez `list`.
+
+Comme la liste est un type qui contient des types internes, mettez-les entre crochets :
+
+{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
-Ces types internes entre crochets sont appelés des "paramÚtres de type".
+/// info
+
+Ces types internes entre crochets sont appelés « paramÚtres de type ».
-Ici, `str` est un paramÚtre de type passé à `List`.
+Dans ce cas, `str` est le paramÚtre de type passé à `list`.
///
-Ce qui signifie : "la variable `items` est une `list`, et chacun de ses éléments a pour type `str`.
+Cela signifie : « la variable `items` est une `list`, et chacun des éléments de cette liste est un `str` ».
-En faisant cela, votre Ă©diteur pourra vous aider, mĂȘme pendant que vous traitez des Ă©lĂ©ments de la liste.
+En faisant cela, votre Ă©diteur peut vous fournir de l'aide mĂȘme pendant le traitement des Ă©lĂ©ments de la liste :
<img src="/img/python-types/image05.png">
Sans types, c'est presque impossible à réaliser.
-Vous remarquerez que la variable `item` n'est qu'un des éléments de la list `items`.
+Remarquez que la variable `item` est l'un des éléments de la liste `items`.
-Et pourtant, l'éditeur sait qu'elle est de type `str` et pourra donc vous aider à l'utiliser.
+Et pourtant, l'éditeur sait que c'est un `str` et fournit le support approprié.
-#### `Tuple` et `Set`
+#### Tuple et Set { #tuple-and-set }
-C'est le mĂȘme fonctionnement pour dĂ©clarer un `tuple` ou un `set` :
+Vous feriez la mĂȘme chose pour dĂ©clarer des `tuple` et des `set` :
-{*../../docs_src/python_types/tutorial007.py hl[1,4] *}
+{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
-Dans cet exemple :
+Cela signifie :
-* La variable `items_t` est un `tuple` avec 3 éléments, un `int`, un deuxiÚme `int`, et un `str`.
+* La variable `items_t` est un `tuple` avec 3 éléments, un `int`, un autre `int`, et un `str`.
* La variable `items_s` est un `set`, et chacun de ses éléments est de type `bytes`.
-#### `Dict`
+#### Dict { #dict }
+
+Pour définir un `dict`, vous passez 2 paramÚtres de type, séparés par des virgules.
+
+Le premier paramÚtre de type est pour les clés du `dict`.
+
+Le second paramĂštre de type est pour les valeurs du `dict` :
+
+{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
+
+Cela signifie :
+
+* La variable `prices` est un `dict` :
+ * Les clés de ce `dict` sont de type `str` (disons, le nom de chaque article).
+ * Les valeurs de ce `dict` sont de type `float` (disons, le prix de chaque article).
+
+#### Union { #union }
+
+Vous pouvez dĂ©clarer qu'une variable peut ĂȘtre de plusieurs types, par exemple, un `int` ou un `str`.
+
+Dans Python 3.6 et supérieur (y compris Python 3.10), vous pouvez utiliser le type `Union` de `typing` et mettre entre crochets les types possibles à accepter.
+
+Dans Python 3.10, il existe aussi une nouvelle syntaxe oĂč vous pouvez mettre les types possibles sĂ©parĂ©s par une <abbr title='aussi appelĂ© « opĂ©rateur OU bit Ă bit », mais ce sens nâest pas pertinent ici'>barre verticale (`|`)</abbr>.
+
+//// tab | Python 3.10+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008b_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008b_py39.py!}
+```
+
+////
+
+Dans les deux cas, cela signifie que `item` peut ĂȘtre un `int` ou un `str`.
+
+#### Possiblement `None` { #possibly-none }
+
+Vous pouvez dĂ©clarer qu'une valeur peut avoir un type, comme `str`, mais qu'elle peut aussi ĂȘtre `None`.
+
+Dans Python 3.6 et supérieur (y compris Python 3.10), vous pouvez le déclarer en important et en utilisant `Optional` depuis le module `typing`.
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009_py39.py!}
+```
+
+Utiliser `Optional[str]` au lieu de simplement `str` permettra Ă l'Ă©diteur de vous aider Ă dĂ©tecter des erreurs oĂč vous supposeriez qu'une valeur est toujours un `str`, alors qu'elle pourrait en fait aussi ĂȘtre `None`.
+
+`Optional[Something]` est en réalité un raccourci pour `Union[Something, None]`, ils sont équivalents.
+
+Cela signifie aussi que dans Python 3.10, vous pouvez utiliser `Something | None` :
+
+//// tab | Python 3.10+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial009_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009_py39.py!}
+```
+
+////
+
+//// tab | Python 3.9+ alternative
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009b_py39.py!}
+```
+
+////
+
+#### Utiliser `Union` ou `Optional` { #using-union-or-optional }
+
+Si vous utilisez une version de Python inférieure à 3.10, voici un conseil de mon point de vue trÚs **subjectif** :
+
+* đš Ăvitez d'utiliser `Optional[SomeType]`
+* Ă la place âš **utilisez `Union[SomeType, None]`** âš.
+
+Les deux sont Ă©quivalents et sous le capot ce sont les mĂȘmes, mais je recommanderais `Union` plutĂŽt que `Optional` parce que le mot « facultatif » semble impliquer que la valeur est optionnelle, alors que cela signifie en fait « elle peut ĂȘtre `None` », mĂȘme si elle n'est pas facultative et est toujours requise.
+
+Je pense que `Union[SomeType, None]` est plus explicite sur ce que cela signifie.
-Pour définir un `dict`, il faut lui passer 2 paramÚtres, séparés par une virgule (`,`).
+Il ne s'agit que des mots et des noms. Mais ces mots peuvent influencer la maniÚre dont vous et vos coéquipiers pensez au code.
-Le premier paramÚtre de type est pour les clés et le second pour les valeurs du dictionnaire (`dict`).
+Par exemple, prenons cette fonction :
-{*../../docs_src/python_types/tutorial008.py hl[1,4] *}
+{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
-Dans cet exemple :
+Le paramÚtre `name` est défini comme `Optional[str]`, mais il n'est pas facultatif, vous ne pouvez pas appeler la fonction sans le paramÚtre :
-* La variable `prices` est de type `dict` :
- * Les clés de ce dictionnaire sont de type `str`.
- * Les valeurs de ce dictionnaire sont de type `float`.
+```Python
+say_hi() # Oh non, cela lĂšve une erreur ! đ±
+```
+
+Le paramÚtre `name` est toujours requis (pas « optionnel ») parce qu'il n'a pas de valeur par défaut. Néanmoins, `name` accepte `None` comme valeur :
+
+```Python
+say_hi(name=None) # Cela fonctionne, None est valide đ
+```
-#### `Optional`
+La bonne nouvelle est que, dĂšs que vous ĂȘtes sur Python 3.10, vous n'avez plus Ă vous en soucier, car vous pourrez simplement utiliser `|` pour dĂ©finir des unions de types :
-Vous pouvez aussi utiliser `Optional` pour dĂ©clarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi ĂȘtre `None`.
+{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
-{*../../docs_src/python_types/tutorial009.py hl[1,4] *}
+Et alors vous n'aurez plus Ă vous soucier de noms comme `Optional` et `Union`. đ
-Utiliser `Optional[str]` plutĂŽt que `str` permettra Ă l'Ă©diteur de vous aider Ă dĂ©tecter les erreurs oĂč vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi ĂȘtre `None`.
+#### Types génériques { #generic-types }
-#### Types génériques
+Ces types qui prennent des paramÚtres de type entre crochets sont appelés des **types génériques** ou **Generics**, par exemple :
-Les types qui peuvent contenir des paramĂštres de types entre crochets, comme :
+//// tab | Python 3.10+
-* `List`
-* `Tuple`
-* `Set`
-* `Dict`
+Vous pouvez utiliser les mĂȘmes types intĂ©grĂ©s comme gĂ©nĂ©riques (avec des crochets et des types Ă l'intĂ©rieur) :
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+Et, comme avec les versions précédentes de Python, depuis le module `typing` :
+
+* `Union`
* `Optional`
-* ...et d'autres.
+* ... et d'autres.
-sont appelés des **types génériques** ou **Generics**.
+Dans Python 3.10, comme alternative Ă l'utilisation des gĂ©nĂ©riques `Union` et `Optional`, vous pouvez utiliser la <abbr title='aussi appelĂ© « opĂ©rateur OU bit Ă bit », mais ce sens nâest pas pertinent ici'>barre verticale (`|`)</abbr> pour dĂ©clarer des unions de types, c'est bien mieux et plus simple.
-### Classes en tant que types
+////
-Vous pouvez aussi déclarer une classe comme type d'une variable.
+//// tab | Python 3.9+
+
+Vous pouvez utiliser les mĂȘmes types intĂ©grĂ©s comme gĂ©nĂ©riques (avec des crochets et des types Ă l'intĂ©rieur) :
+
+* `list`
+* `tuple`
+* `set`
+* `dict`
+
+Et des génériques depuis le module `typing` :
+
+* `Union`
+* `Optional`
+* ... et d'autres.
+
+////
+
+### Classes en tant que types { #classes-as-types }
-Disons que vous avez une classe `Person`, avec une variable `name` :
+Vous pouvez aussi déclarer une classe comme type d'une variable.
-{*../../docs_src/python_types/tutorial010.py hl[1:3] *}
+Disons que vous avez une classe `Person`, avec un nom :
+{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
Vous pouvez ensuite déclarer une variable de type `Person` :
-{*../../docs_src/python_types/tutorial010.py hl[6] *}
+{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
-Et vous aurez accÚs, encore une fois, au support complet offert par l'éditeur :
+Et là encore, vous obtenez tout le support de l'éditeur :
<img src="/img/python-types/image06.png">
-## Les modĂšles Pydantic
+Remarquez que cela signifie « `one_person` est une instance de la classe `Person` ».
+
+Cela ne signifie pas « `one_person` est la classe appelée `Person` ».
+
+## ModĂšles Pydantic { #pydantic-models }
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> est une bibliothÚque Python pour effectuer de la validation de données.
-Vous déclarez la forme de la donnée avec des classes et des attributs.
+Vous déclarez la « forme » de la donnée sous forme de classes avec des attributs.
-Chaque attribut possĂšde un type.
+Et chaque attribut a un type.
-Puis vous créez une instance de cette classe avec certaines valeurs et **Pydantic** validera les valeurs, les convertira dans le type adéquat (si c'est nécessaire et possible) et vous donnera un objet avec toute la donnée.
+Ensuite, vous créez une instance de cette classe avec certaines valeurs et elle validera les valeurs, les convertira dans le type approprié (le cas échéant) et vous donnera un objet avec toutes les données.
-Ainsi, votre éditeur vous offrira un support adapté pour l'objet résultant.
+Et vous obtenez tout le support de l'éditeur avec cet objet résultant.
-Extrait de la documentation officielle de **Pydantic** :
+Un exemple tiré de la documentation officielle de Pydantic :
-{*../../docs_src/python_types/tutorial011.py*}
+{* ../../docs_src/python_types/tutorial011_py310.py *}
/// info
-Pour en savoir plus Ă propos de <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, allez jeter un coup d'oeil Ă sa documentation</a>.
+Pour en savoir plus Ă propos de <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, consultez sa documentation</a>.
+
+///
+
+**FastAPI** est entiÚrement basé sur Pydantic.
+
+Vous verrez beaucoup plus de tout cela en pratique dans le [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
+
+/// tip | Astuce
+
+Pydantic a un comportement spécial lorsque vous utilisez `Optional` ou `Union[Something, None]` sans valeur par défaut, vous pouvez en lire davantage dans la documentation de Pydantic à propos des <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">champs Optionals requis</a>.
///
-**FastAPI** est basé entiÚrement sur **Pydantic**.
+## Annotations de type avec métadonnées { #type-hints-with-metadata-annotations }
+
+Python dispose également d'une fonctionnalité qui permet de mettre des **<abbr title="Données sur les données, dans ce cas, des informations sur le type, p. ex. une description.">métadonnées</abbr> supplémentaires** dans ces annotations de type en utilisant `Annotated`.
+
+Depuis Python 3.9, `Annotated` fait partie de la bibliothĂšque standard, vous pouvez donc l'importer depuis `typing`.
-Vous verrez bien plus d'exemples de son utilisation dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
+{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
+
+Python lui-mĂȘme ne fait rien avec ce `Annotated`. Et pour les Ă©diteurs et autres outils, le type est toujours `str`.
+
+Mais vous pouvez utiliser cet espace dans `Annotated` pour fournir à **FastAPI** des métadonnées supplémentaires sur la façon dont vous voulez que votre application se comporte.
+
+L'important à retenir est que le premier paramÚtre de type que vous passez à `Annotated` est le type réel. Le reste n'est que des métadonnées pour d'autres outils.
+
+Pour l'instant, vous avez juste besoin de savoir que `Annotated` existe, et que c'est du Python standard. đ
+
+Plus tard, vous verrez Ă quel point cela peut ĂȘtre puissant.
+
+/// tip | Astuce
+
+Le fait que ce soit du Python standard signifie que vous bĂ©nĂ©ficierez toujours de la meilleure expĂ©rience dĂ©veloppeur possible dans votre Ă©diteur, avec les outils que vous utilisez pour analyser et refactoriser votre code, etc. âš
+
+Et aussi que votre code sera trĂšs compatible avec de nombreux autres outils et bibliothĂšques Python. đ
+
+///
-## Les annotations de type dans **FastAPI**
+## Annotations de type dans **FastAPI** { #type-hints-in-fastapi }
-**FastAPI** utilise ces annotations pour faire différentes choses.
+**FastAPI** tire parti de ces annotations de type pour faire plusieurs choses.
-Avec **FastAPI**, vous déclarez des paramÚtres grùce aux annotations de types et vous obtenez :
+Avec **FastAPI**, vous déclarez des paramÚtres avec des annotations de type et vous obtenez :
-* **du support de l'éditeur**
-* **de la vérification de types**
+* **Du support de l'éditeur**.
+* **Des vérifications de types**.
-...et **FastAPI** utilise ces mĂȘmes dĂ©clarations pour :
+... et **FastAPI** utilise les mĂȘmes dĂ©clarations pour :
-* **DĂ©finir les prĂ©requis** : depuis les paramĂštres de chemins des requĂȘtes, les entĂȘtes, les corps, les dĂ©pendances, etc.
-* **Convertir des donnĂ©es** : depuis la requĂȘte vers les types requis.
-* **Valider des donnĂ©es** : venant de chaque requĂȘte :
- * Générant automatiquement des **erreurs** renvoyées au client quand la donnée est invalide.
+* **DĂ©finir des prĂ©requis** : Ă partir des paramĂštres de chemin de la requĂȘte, des paramĂštres de requĂȘte, des en-tĂȘtes, des corps, des dĂ©pendances, etc.
+* **Convertir des donnĂ©es** : de la requĂȘte vers le type requis.
+* **Valider des donnĂ©es** : provenant de chaque requĂȘte :
+ * En générant des **erreurs automatiques** renvoyées au client lorsque la donnée est invalide.
* **Documenter** l'API avec OpenAPI :
- * ce qui ensuite utilisé par les interfaces utilisateur automatiques de documentation interactive.
+ * ce qui est ensuite utilisé par les interfaces utilisateur de documentation interactive automatiques.
-Tout cela peut paraßtre bien abstrait, mais ne vous inquiétez pas, vous verrez tout ça en pratique dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
+Tout cela peut sembler abstrait. Ne vous inquiétez pas. Vous verrez tout cela en action dans le [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
-Ce qu'il faut retenir c'est qu'en utilisant les types standard de Python, à un seul endroit (plutÎt que d'ajouter plus de classes, de décorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous.
+L'important est qu'en utilisant les types standards de Python, en un seul endroit (au lieu d'ajouter plus de classes, de décorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous.
/// info
-Si vous avez dĂ©jĂ lu le tutoriel et ĂȘtes revenus ici pour voir plus sur les types, une bonne ressource est la <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"cheat sheet" de `mypy`</a>.
+Si vous avez dĂ©jĂ parcouru tout le tutoriel et ĂȘtes revenu pour en voir plus sur les types, une bonne ressource est <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">l'« aide-mĂ©moire » de `mypy`</a>.
///
-# TĂąches d'arriĂšre-plan
+# TĂąches d'arriĂšre-plan { #background-tasks }
Vous pouvez définir des tùches d'arriÚre-plan qui seront exécutées aprÚs avoir retourné une réponse.
Cela comprend, par exemple :
* Les notifications par email envoyées aprÚs l'exécution d'une action :
- * Ătant donnĂ© que se connecter Ă un serveur et envoyer un email a tendance Ă ĂȘtre «lent» (plusieurs secondes), vous pouvez retourner la rĂ©ponse directement et envoyer la notification en arriĂšre-plan.
+ * Ătant donnĂ© que se connecter Ă un serveur et envoyer un email a tendance Ă ĂȘtre « lent » (plusieurs secondes), vous pouvez retourner la rĂ©ponse directement et envoyer la notification en arriĂšre-plan.
* Traiter des données :
- * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arriÚre-plan.
+ * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse « Accepted » (HTTP 202) puis faire le traitement en arriÚre-plan.
+## Utiliser `BackgroundTasks` { #using-backgroundtasks }
-## Utiliser `BackgroundTasks`
+Pour commencer, importez `BackgroundTasks` et définissez un paramÚtre dans votre *fonction de chemin d'accÚs* avec `BackgroundTasks` comme type déclaré.
-Pour commencer, importez `BackgroundTasks` et définissez un paramÚtre dans votre *fonction de chemin* avec `BackgroundTasks` comme type déclaré.
-
-{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
**FastAPI** créera l'objet de type `BackgroundTasks` pour vous et le passera comme paramÚtre.
-## Créer une fonction de tùche
+## Créer une fonction de tùche { #create-a-task-function }
Une fonction à exécuter comme tùche d'arriÚre-plan est juste une fonction standard qui peut recevoir des paramÚtres.
L'opération d'écriture n'utilisant ni `async` ni `await`, on définit la fonction avec un `def` normal.
-{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
-
-## Ajouter une tĂąche d'arriĂšre-plan
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
-Dans votre *fonction de chemin*, passez votre fonction de tùche à l'objet de type `BackgroundTasks` (`background_tasks` ici) grùce à la méthode `.add_task()` :
+## Ajouter une tĂąche d'arriĂšre-plan { #add-the-background-task }
+Dans votre *fonction de chemin d'accÚs*, passez votre fonction de tùche à l'objet de type `BackgroundTasks` (`background_tasks` ici) grùce à la méthode `.add_task()` :
-{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
+{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
`.add_task()` reçoit comme arguments :
* Les arguments positionnels Ă passer Ă la fonction de tĂąche dans l'ordre (`email`).
* Les arguments nommés à passer à la fonction de tùche (`message="some notification"`).
-## Injection de dépendances
+## Injection de dépendances { #dependency-injection }
-Utiliser `BackgroundTasks` fonctionne aussi avec le systÚme d'injection de dépendances. Vous pouvez déclarer un paramÚtre de type `BackgroundTasks` à différents niveaux : dans une *fonction de chemin*, dans une dépendance, dans une sous-dépendance...
+Utiliser `BackgroundTasks` fonctionne aussi avec le systÚme d'injection de dépendances. Vous pouvez déclarer un paramÚtre de type `BackgroundTasks` à différents niveaux : dans une *fonction de chemin d'accÚs*, dans une dépendance (dependable), dans une sous-dépendance, etc.
-**FastAPI** sait quoi faire dans chaque cas et comment rĂ©utiliser le mĂȘme objet, afin que tous les paramĂštres de type `BackgroundTasks` soient fusionnĂ©s et que les tĂąches soient exĂ©cutĂ©es en arriĂšre-plan :
+**FastAPI** sait quoi faire dans chaque cas et comment rĂ©utiliser le mĂȘme objet, afin que toutes les tĂąches d'arriĂšre-plan soient fusionnĂ©es et que les tĂąches soient ensuite exĂ©cutĂ©es en arriĂšre-plan :
-{* ../../docs_src/background_tasks/tutorial002.py hl[13,15,22,25] *}
+{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
Dans cet exemple, les messages seront écrits dans le fichier `log.txt` aprÚs que la réponse soit envoyée.
-S'il y avait une `query` (paramĂštre nommĂ© `q`) dans la requĂȘte, alors elle sera Ă©crite dans `log.txt` via une tĂąche d'arriĂšre-plan.
+S'il y avait un paramĂštre de requĂȘte dans la requĂȘte, alors il sera Ă©crit dans le journal via une tĂąche d'arriĂšre-plan.
-Et ensuite une autre tùche d'arriÚre-plan (générée dans les paramÚtres de la *la fonction de chemin*) écrira un message dans `log.txt` comprenant le paramÚtre de chemin `email`.
+Et ensuite une autre tùche d'arriÚre-plan (générée dans la *fonction de chemin d'accÚs*) écrira un message comprenant le paramÚtre de chemin `email`.
-## Détails techniques
+## Détails techniques { #technical-details }
La classe `BackgroundTasks` provient directement de <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">`starlette.background`</a>.
Elle est importée/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et éviter d'importer accidentellement `BackgroundTask` (sans `s` à la fin) depuis `starlette.background`.
-En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramÚtre de *fonction de chemin* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
+En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramÚtre de *fonction de chemin d'accÚs* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
Il est tout de mĂȘme possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut crĂ©er l'objet dans le code et renvoyer une `Response` Starlette l'incluant.
-Plus de détails sont disponibles dans <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">la documentation officielle de Starlette sur les tùches d'arriÚre-plan</a> (via leurs classes `BackgroundTasks`et `BackgroundTask`).
+Plus de détails sont disponibles dans <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">la documentation officielle de Starlette sur les tùches d'arriÚre-plan</a>.
-## Avertissement
+## Avertissement { #caveat }
Si vous avez besoin de rĂ©aliser des traitements lourds en tĂąche d'arriĂšre-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le mĂȘme process (par exemple, pas besoin de partager la mĂ©moire, les variables, etc.), il peut s'avĂ©rer profitable d'utiliser des outils plus importants tels que <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
-Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tùches d'arriÚre-plan dans différents process, et potentiellement, sur plusieurs serveurs.
+Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tùches d'arriÚre-plan dans différents process, et surtout, sur plusieurs serveurs.
Mais si vous avez besoin d'accĂ©der aux variables et objets de la mĂȘme application **FastAPI**, ou si vous avez besoin d'effectuer de petites tĂąches d'arriĂšre-plan (comme envoyer des notifications par email), vous pouvez simplement vous contenter d'utiliser `BackgroundTasks`.
-## Résumé
+## Résumé { #recap }
-Importez et utilisez `BackgroundTasks` grùce aux paramÚtres de *fonction de chemin* et les dépendances pour ajouter des tùches d'arriÚre-plan.
+Importez et utilisez `BackgroundTasks` grùce aux paramÚtres de *fonction de chemin d'accÚs* et les dépendances pour ajouter des tùches d'arriÚre-plan.
-# Body - ParamĂštres multiples
+# Body - ParamĂštres multiples { #body-multiple-parameters }
-Maintenant que nous avons vu comment manipuler `Path` et `Query`, voyons comment faire pour le corps d'une requĂȘte, communĂ©ment dĂ©signĂ© par le terme anglais "body".
+Maintenant que nous avons vu comment utiliser `Path` et `Query`, voyons des usages plus avancĂ©s des dĂ©clarations de paramĂštres du corps de la requĂȘte.
-## Mélanger les paramÚtres `Path`, `Query` et body
+## Mélanger les paramÚtres `Path`, `Query` et body { #mix-path-query-and-body-parameters }
-Tout d'abord, sachez que vous pouvez mélanger les déclarations des paramÚtres `Path`, `Query` et body, **FastAPI** saura quoi faire.
+Tout d'abord, sachez que vous pouvez mélanger librement les déclarations des paramÚtres `Path`, `Query` et du body, **FastAPI** saura quoi faire.
-Vous pouvez également déclarer des paramÚtres body comme étant optionnels, en leur assignant une valeur par défaut à `None` :
+Et vous pouvez également déclarer des paramÚtres du body comme étant optionnels, en leur assignant une valeur par défaut à `None` :
{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
-/// note
+/// note | Remarque
-Notez que, dans ce cas, le paramÚtre `item` provenant du `Body` est optionnel (sa valeur par défaut est `None`).
+Notez que, dans ce cas, l'élément `item` récupéré depuis le body est optionnel. Comme sa valeur par défaut est `None`.
///
-## ParamĂštres multiples du body
+## ParamĂštres multiples du body { #multiple-body-parameters }
-Dans l'exemple précédent, les opérations de routage attendaient un body JSON avec les attributs d'un `Item`, par exemple :
+Dans l'exemple précédent, les chemins d'accÚs attendraient un body JSON avec les attributs d'un `Item`, par exemple :
```JSON
{
}
```
-Mais vous pouvez également déclarer plusieurs paramÚtres provenant de body, par exemple `item` et `user` simultanément :
+Mais vous pouvez également déclarer plusieurs paramÚtres provenant du body, par exemple `item` et `user` :
{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *}
-Dans ce cas, **FastAPI** détectera qu'il y a plus d'un paramÚtre dans le body (chacun correspondant à un modÚle Pydantic).
+Dans ce cas, **FastAPI** détectera qu'il y a plus d'un paramÚtre du body dans la fonction (il y a deux paramÚtres qui sont des modÚles Pydantic).
-Il utilisera alors les noms des paramÚtres comme clés, et s'attendra à recevoir quelque chose de semblable à :
+Il utilisera alors les noms des paramÚtres comme clés (noms de champs) dans le body, et s'attendra à recevoir un body semblable à :
```JSON
{
}
```
-/// note
+/// note | Remarque
-"Notez que, bien que nous ayons dĂ©clarĂ© le paramĂštre `item` de la mĂȘme maniĂšre que prĂ©cĂ©demment, il est maintenant associĂ© Ă la clĂ© `item` dans le corps de la requĂȘte."`.
+Notez que, bien que `item` ait Ă©tĂ© dĂ©clarĂ© de la mĂȘme maniĂšre qu'auparavant, il est dĂ©sormais attendu Ă l'intĂ©rieur du body sous la clĂ© `item`.
///
-**FastAPI** effectue la conversion de la requĂȘte de façon transparente, de sorte que les objets `item` et `user` se trouvent correctement dĂ©finis.
+**FastAPI** effectuera la conversion automatique depuis la requĂȘte, de sorte que le paramĂštre `item` reçoive son contenu spĂ©cifique, et de mĂȘme pour `user`.
-Il effectue Ă©galement la validation des donnĂ©es (mĂȘme imbriquĂ©es les unes dans les autres), et permet de les documenter correctement (schĂ©ma OpenAPI et documentation auto-gĂ©nĂ©rĂ©e).
+Il effectuera la validation des données composées, et les documentera ainsi pour le schéma OpenAPI et la documentation automatique.
-## Valeurs scalaires dans le body
+## Valeurs singuliĂšres dans le body { #singular-values-in-body }
-De la mĂȘme façon qu'il existe `Query` et `Path` pour dĂ©finir des donnĂ©es supplĂ©mentaires pour les paramĂštres query et path, **FastAPI** fournit un Ă©quivalent `Body`.
+De la mĂȘme façon qu'il existe `Query` et `Path` pour dĂ©finir des donnĂ©es supplĂ©mentaires pour les paramĂštres de requĂȘte et de chemin, **FastAPI** fournit un Ă©quivalent `Body`.
-Par exemple, en Ă©tendant le modĂšle prĂ©cĂ©dent, vous pouvez vouloir ajouter un paramĂštre `importance` dans le mĂȘme body, en plus des paramĂštres `item` et `user`.
+Par exemple, en Ă©tendant le modĂšle prĂ©cĂ©dent, vous pourriez dĂ©cider d'avoir une autre clĂ© `importance` dans le mĂȘme body, en plus de `item` et `user`.
-Si vous le dĂ©clarez tel quel, comme c'est une valeur [scalaire](https://docs.github.com/fr/graphql/reference/scalars), **FastAPI** supposera qu'il s'agit d'un paramĂštre de requĂȘte (`Query`).
+Si vous le dĂ©clarez tel quel, comme c'est une valeur singuliĂšre, **FastAPI** supposera qu'il s'agit d'un paramĂštre de requĂȘte.
-Mais vous pouvez indiquer Ă **FastAPI** de la traiter comme une variable de body en utilisant `Body` :
+Mais vous pouvez indiquer à **FastAPI** de la traiter comme une autre clé du body en utilisant `Body` :
{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *}
}
```
-Encore une fois, cela convertira les types de données, les validera, permettra de générer la documentation, etc...
+Encore une fois, il convertira les types de données, validera, documentera, etc.
-## ParamĂštres multiples body et query
+## ParamĂštres multiples du body et paramĂštres de requĂȘte { #multiple-body-params-and-query }
-Bien entendu, vous pouvez déclarer autant de paramÚtres que vous le souhaitez, en plus des paramÚtres body déjà déclarés.
+Bien entendu, vous pouvez Ă©galement dĂ©clarer des paramĂštres de requĂȘte supplĂ©mentaires quand vous en avez besoin, en plus de tout paramĂštre du body.
-Par défaut, les valeurs [scalaires](https://docs.github.com/fr/graphql/reference/scalars) sont interprétées comme des paramÚtres query, donc inutile d'ajouter explicitement `Query`. Vous pouvez juste écrire :
+Comme, par dĂ©faut, les valeurs singuliĂšres sont interprĂ©tĂ©es comme des paramĂštres de requĂȘte, vous n'avez pas besoin d'ajouter explicitement `Query`, vous pouvez simplement Ă©crire :
```Python
-q: Union[str, None] = None
+q: str | None = None
```
-Ou bien, en Python 3.10 et supérieur :
+Ou en Python 3.9 :
```Python
-q: str | None = None
+q: Union[str, None] = None
```
Par exemple :
-{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[27] *}
+{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
/// info
-`Body` possĂšde les mĂȘmes paramĂštres de validation additionnels et de gestion des mĂ©tadonnĂ©es que `Query` et `Path`, ainsi que d'autres que nous verrons plus tard.
+`Body` possĂšde Ă©galement les mĂȘmes paramĂštres supplĂ©mentaires de validation et de mĂ©tadonnĂ©es que `Query`, `Path` et d'autres que vous verrez plus tard.
///
-## Inclure un paramÚtre imbriqué dans le body
+## Intégrer un seul paramÚtre du body { #embed-a-single-body-parameter }
-Disons que vous avez seulement un paramĂštre `item` dans le body, correspondant Ă un modĂšle Pydantic `Item`.
+Supposons que vous n'ayez qu'un seul paramĂštre `item` dans le body, provenant d'un modĂšle Pydantic `Item`.
-Par défaut, **FastAPI** attendra sa déclaration directement dans le body.
+Par défaut, **FastAPI** attendra alors son contenu directement.
-Cependant, si vous souhaitez qu'il interprĂȘte correctement un JSON avec une clĂ© `item` associĂ©e au contenu du modĂšle, comme cela serait le cas si vous dĂ©clariez des paramĂštres body additionnels, vous pouvez utiliser le paramĂštre spĂ©cial `embed` de `Body` :
+Mais si vous voulez qu'il attende un JSON avec une clé `item` contenant le contenu du modÚle, comme lorsqu'on déclare des paramÚtres supplémentaires du body, vous pouvez utiliser le paramÚtre spécial `embed` de `Body` :
```Python
item: Item = Body(embed=True)
```
-Voici un exemple complet :
+comme dans :
{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *}
-Dans ce cas **FastAPI** attendra un body semblable Ă :
+Dans ce cas **FastAPI** s'attendra Ă un body semblable Ă :
```JSON hl_lines="2"
{
}
```
-## Pour résumer
+## Récapitulatif { #recap }
-Vous pouvez ajouter plusieurs paramĂštres body dans votre fonction de routage, mĂȘme si une requĂȘte ne peut avoir qu'un seul body.
+Vous pouvez ajouter plusieurs paramĂštres du body Ă votre fonction de chemin d'accĂšs, mĂȘme si une requĂȘte ne peut avoir qu'un seul body.
-Cependant, **FastAPI** se chargera de faire opérer sa magie, afin de toujours fournir à votre fonction des données correctes, les validera et documentera le schéma associé.
+Mais **FastAPI** s'en chargera, vous fournira les bonnes données dans votre fonction, et validera et documentera le schéma correct dans le chemin d'accÚs.
-Vous pouvez également déclarer des valeurs [scalaires](https://docs.github.com/fr/graphql/reference/scalars) à recevoir dans le body.
+Vous pouvez également déclarer des valeurs singuliÚres à recevoir dans le body.
-Et vous pouvez indiquer Ă **FastAPI** d'inclure le body dans une autre variable, mĂȘme lorsqu'un seul paramĂštre est dĂ©clarĂ©.
+Et vous pouvez indiquer Ă **FastAPI** d'intĂ©grer le body sous une clĂ© mĂȘme lorsqu'un seul paramĂštre est dĂ©clarĂ©.
-# Corps de la requĂȘte
+# Corps de la requĂȘte { #request-body }
Quand vous avez besoin d'envoyer de la donnĂ©e depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de requĂȘte**.
Le corps d'une **requĂȘte** est de la donnĂ©e envoyĂ©e par le client Ă votre API. Le corps d'une **rĂ©ponse** est la donnĂ©e envoyĂ©e par votre API au client.
-Votre API aura presque toujours Ă envoyer un corps de **rĂ©ponse**. Mais un client n'a pas toujours Ă envoyer un corps de **requĂȘte**.
+Votre API aura presque toujours Ă envoyer un corps de **rĂ©ponse**. Mais un client n'a pas toujours Ă envoyer un **corps de requĂȘte** : parfois il demande seulement un chemin, peut-ĂȘtre avec quelques paramĂštres de requĂȘte, mais n'envoie pas de corps.
Pour dĂ©clarer un corps de **requĂȘte**, on utilise les modĂšles de <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> en profitant de tous leurs avantages et fonctionnalitĂ©s.
///
-## Importez le `BaseModel` de Pydantic
+## Importer le `BaseModel` de Pydantic { #import-pydantics-basemodel }
Commencez par importer la classe `BaseModel` du module `pydantic` :
-{* ../../docs_src/body/tutorial001.py hl[4] *}
+{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
-## Créez votre modÚle de données
+## Créer votre modÚle de données { #create-your-data-model }
Déclarez ensuite votre modÚle de données en tant que classe qui hérite de `BaseModel`.
Utilisez les types Python standard pour tous les attributs :
-{* ../../docs_src/body/tutorial001.py hl[7:11] *}
+{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
-Tout comme pour la dĂ©claration de paramĂštres de requĂȘte, quand un attribut de modĂšle a une valeur par dĂ©faut, il n'est pas nĂ©cessaire. Sinon, cet attribut doit ĂȘtre renseignĂ© dans le corps de la requĂȘte. Pour rendre ce champ optionnel simplement, utilisez `None` comme valeur par dĂ©faut.
+Tout comme pour la dĂ©claration de paramĂštres de requĂȘte, quand un attribut de modĂšle a une valeur par dĂ©faut, il n'est pas nĂ©cessaire. Sinon, cet attribut doit ĂȘtre renseignĂ© dans le corps de la requĂȘte. Utilisez `None` pour le rendre simplement optionnel.
-Par exemple, le modÚle ci-dessus déclare un "objet" JSON (ou `dict` Python) tel que :
+Par exemple, le modÚle ci-dessus déclare un JSON « `object` » (ou `dict` Python) tel que :
```JSON
{
}
```
-...`description` et `tax` étant des attributs optionnels (avec `None` comme valeur par défaut), cet "objet" JSON serait aussi valide :
+... `description` et `tax` étant des attributs optionnels (avec `None` comme valeur par défaut), ce JSON « `object` » serait aussi valide :
```JSON
{
}
```
-## Déclarez-le comme paramÚtre
+## Le déclarer comme paramÚtre { #declare-it-as-a-parameter }
Pour l'ajouter Ă votre *opĂ©ration de chemin*, dĂ©clarez-le comme vous dĂ©clareriez des paramĂštres de chemin ou de requĂȘte :
-{* ../../docs_src/body/tutorial001.py hl[18] *}
+{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
-...et déclarez que son type est le modÚle que vous avez créé : `Item`.
+... et déclarez que son type est le modÚle que vous avez créé : `Item`.
-## Résultats
+## Résultats { #results }
En utilisant uniquement les déclarations de type Python, **FastAPI** réussit à :
* Lire le contenu de la requĂȘte en tant que JSON.
* Convertir les types correspondants (si nécessaire).
* Valider la donnée.
- * Si la donnĂ©e est invalide, une erreur propre et claire sera renvoyĂ©e, indiquant exactement oĂč Ă©tait la donnĂ©e incorrecte.
+ * Si la donnĂ©e est invalide, une erreur propre et claire sera renvoyĂ©e, indiquant exactement oĂč et quelle Ă©tait la donnĂ©e incorrecte.
* Passer la donnée reçue dans le paramÚtre `item`.
- * Ce paramÚtre ayant été déclaré dans la fonction comme étant de type `Item`, vous aurez aussi tout le support offert par l'éditeur (auto-complétion, etc.) pour tous les attributs de ce paramÚtre et les types de ces attributs.
-* GĂ©nĂ©rer des dĂ©finitions <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> pour votre modĂšle, qui peuvent ĂȘtre utilisĂ©es oĂč vous en avez besoin dans votre projet ensuite.
-* Ces schémas participeront à la constitution du schéma généré OpenAPI, et seront donc utilisés par les documentations automatiquement générées.
+ * Ce paramÚtre ayant été déclaré dans la fonction comme étant de type `Item`, vous aurez aussi tout le support offert par l'éditeur (autocomplétion, etc.) pour tous les attributs de ce paramÚtre et les types de ces attributs.
+* Générer des définitions <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> pour votre modÚle ; vous pouvez également les utiliser partout ailleurs si cela a du sens pour votre projet.
+* Ces schémas participeront à la constitution du schéma généré OpenAPI, et seront utilisés par les documentations automatiques <abbr title="User Interfaces - Interfaces utilisateur">UIs</abbr>.
-## Documentation automatique
+## Documentation automatique { #automatic-docs }
Les schémas JSON de vos modÚles seront intégrés au schéma OpenAPI global de votre application, et seront donc affichés dans la documentation interactive de l'API :
<img src="/img/tutorial/body/image02.png">
-## Support de l'éditeur
+## Support de l'éditeur { #editor-support }
-Dans votre éditeur, vous aurez des annotations de types et de l'auto-complétion partout dans votre fonction (ce qui n'aurait pas été le cas si vous aviez utilisé un classique `dict` plutÎt qu'un modÚle Pydantic) :
+Dans votre éditeur, vous aurez des annotations de type et de l'autocomplétion partout dans votre fonction (ce qui n'aurait pas été le cas si vous aviez reçu un `dict` plutÎt qu'un modÚle Pydantic) :
<img src="/img/tutorial/body/image03.png">
-Et vous obtenez aussi de la vérification d'erreur pour les opérations incorrectes de types :
+Et vous obtenez aussi des vérifications d'erreurs pour les opérations de types incorrectes :
<img src="/img/tutorial/body/image04.png">
Ce n'est pas un hasard, ce framework entier a été bùti avec ce design comme objectif.
-Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour s'assurer que cela fonctionnerait avec tous les éditeurs.
+Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour vous assurer que cela fonctionnerait avec tous les éditeurs.
Des changements sur Pydantic ont mĂȘme Ă©tĂ© faits pour supporter cela.
-Les captures d'écrans précédentes ont été prises sur <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>.
+Les captures d'écran précédentes ont été prises sur <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>.
-Mais vous auriez le mĂȘme support de l'Ă©diteur avec <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> et la majoritĂ© des autres Ă©diteurs de code Python.
+Mais vous auriez le mĂȘme support de l'Ă©diteur avec <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> et la majoritĂ© des autres Ă©diteurs de code Python :
<img src="/img/tutorial/body/image05.png">
/// tip | Astuce
-Si vous utilisez <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> comme éditeur, vous pouvez utiliser le Plugin <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
+Si vous utilisez <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> comme éditeur, vous pouvez utiliser le plug-in <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
Ce qui améliore le support pour les modÚles Pydantic avec :
-* de l'auto-complétion
+* de l'autocomplétion
* des vérifications de type
-* du "refactoring" (ou remaniement de code)
+* du « refactoring » (ou remaniement de code)
* de la recherche
-* de l'inspection
+* des inspections
///
-## Utilisez le modĂšle
+## Utiliser le modĂšle { #use-the-model }
Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modÚle directement :
-{* ../../docs_src/body/tutorial002.py hl[21] *}
+{* ../../docs_src/body/tutorial002_py310.py *}
-## Corps de la requĂȘte + paramĂštres de chemin
+## Corps de la requĂȘte + paramĂštres de chemin { #request-body-path-parameters }
Vous pouvez dĂ©clarer des paramĂštres de chemin et un corps de requĂȘte pour la mĂȘme *opĂ©ration de chemin*.
**FastAPI** est capable de reconnaĂźtre que les paramĂštres de la fonction qui correspondent aux paramĂštres de chemin doivent ĂȘtre **rĂ©cupĂ©rĂ©s depuis le chemin**, et que les paramĂštres de fonctions dĂ©clarĂ©s comme modĂšles Pydantic devraient ĂȘtre **rĂ©cupĂ©rĂ©s depuis le corps de la requĂȘte**.
-{* ../../docs_src/body/tutorial003.py hl[17:18] *}
+{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
-## Corps de la requĂȘte + paramĂštres de chemin et de requĂȘte
+## Corps de la requĂȘte + paramĂštres de chemin et de requĂȘte { #request-body-path-query-parameters }
Vous pouvez aussi dĂ©clarer un **corps**, et des paramĂštres de **chemin** et de **requĂȘte** dans la mĂȘme *opĂ©ration de chemin*.
**FastAPI** saura reconnaßtre chacun d'entre eux et récupérer la bonne donnée au bon endroit.
-{* ../../docs_src/body/tutorial004.py hl[18] *}
+{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
Les paramĂštres de la fonction seront reconnus comme tel :
* Si le paramĂštre est d'un **type singulier** (comme `int`, `float`, `str`, `bool`, etc.), il sera interprĂ©tĂ© comme un paramĂštre de **requĂȘte**.
* Si le paramĂštre est dĂ©clarĂ© comme ayant pour type un **modĂšle Pydantic**, il sera interprĂ©tĂ© comme faisant partie du **corps** de la requĂȘte.
-/// note
+/// note | Remarque
-**FastAPI** saura que la valeur de `q` n'est pas requise grùce à la valeur par défaut `=None`.
+**FastAPI** saura que la valeur de `q` n'est pas requise grùce à la valeur par défaut `= None`.
-Le type `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI**, mais sera utile à votre éditeur pour améliorer le support offert par ce dernier et détecter plus facilement des erreurs de type.
+L'annotation de type `str | None` (Python 3.10+) ou `Union` dans `Union[str, None]` (Python 3.9+) n'est pas utilisée par **FastAPI** pour déterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par défaut `= None`.
+
+Mais ajouter ces annotations de type permettra à votre éditeur de vous offrir un meilleur support et de détecter des erreurs.
///
-## Sans Pydantic
+## Sans Pydantic { #without-pydantic }
-Si vous ne voulez pas utiliser des modĂšles Pydantic, vous pouvez aussi utiliser des paramĂštres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requĂȘte - ParamĂštres multiples](body-multiple-params.md){.internal-link target=_blank}.
+Si vous ne voulez pas utiliser des modĂšles Pydantic, vous pouvez aussi utiliser des paramĂštres de **Body**. Pour cela, allez voir la documentation sur [Corps de la requĂȘte - ParamĂštres multiples : Valeurs singuliĂšres dans le corps](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
-# <abbr title="En anglais: Debugging">Débogage</abbr>
+# <abbr title="En anglais: Debugging">Débogage</abbr> { #debugging }
Vous pouvez connecter le <abbr title="En anglais: debugger">débogueur</abbr> dans votre éditeur, par exemple avec Visual Studio Code ou PyCharm.
-## Faites appel Ă `uvicorn`
+## Appeler `uvicorn` { #call-uvicorn }
Dans votre application FastAPI, importez et exécutez directement `uvicorn` :
-{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
+{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
-### Ă propos de `__name__ == "__main__"`
+### Ă propos de `__name__ == "__main__"` { #about-name-main }
Le but principal de `__name__ == "__main__"` est d'avoir du code qui est exécuté lorsque votre fichier est appelé avec :
from myapp import app
```
-#### Pour davantage de détails
+#### Pour davantage de détails { #more-details }
Imaginons que votre fichier s'appelle `myapp.py`.
///
-## Exécutez votre code avec votre <abbr title="En anglais: debugger">débogueur</abbr>
+## Exécuter votre code avec votre <abbr title="En anglais: debugger">débogueur</abbr> { #run-your-code-with-your-debugger }
Parce que vous exécutez le serveur Uvicorn directement depuis votre code, vous pouvez appeler votre programme Python (votre application FastAPI) directement depuis le <abbr title="En anglais: debugger">débogueur</abbr>.
Par exemple, dans Visual Studio Code, vous pouvez :
-- Cliquer sur l'onglet "Debug" de la barre d'activités de Visual Studio Code.
-- "Add configuration...".
-- Sélectionnez "Python".
-- Lancez le <abbr title="En anglais: debugger">débogueur</abbr> avec l'option "`Python: Current File (Integrated Terminal)`".
+- Allez dans le panneau « Debug ».
+- « Add configuration... ».
+- Sélectionnez « Python ».
+- Lancez le <abbr title="En anglais: debugger">débogueur</abbr> avec l'option « Python: Current File (Integrated Terminal) ».
Il dĂ©marrera alors le serveur avec votre code **FastAPI**, s'arrĂȘtera Ă vos points d'arrĂȘt, etc.
Si vous utilisez Pycharm, vous pouvez :
-- Ouvrir le menu "Run".
-- Sélectionnez l'option "Debug...".
+- Ouvrez le menu « Run ».
+- Sélectionnez l'option « Debug... ».
- Un menu contextuel s'affiche alors.
- Sélectionnez le fichier à déboguer (dans ce cas, `main.py`).
-# Démarrage
+# Démarrage { #first-steps }
-Le fichier **FastAPI** le plus simple possible pourrait ressembler Ă cela :
+Le fichier **FastAPI** le plus simple possible pourrait ressembler Ă ceci :
-{* ../../docs_src/first_steps/tutorial001.py *}
+{* ../../docs_src/first_steps/tutorial001_py39.py *}
-Copiez ce code dans un fichier nommé `main.py`.
+Copiez cela dans un fichier `main.py`.
-Démarrez le serveur :
+Démarrez le serveur en direct :
<div class="termy">
```console
-$ uvicorn main:app --reload
+$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
-<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-<span style="color: green;">INFO</span>: Started reloader process [28720]
-<span style="color: green;">INFO</span>: Started server process [28722]
-<span style="color: green;">INFO</span>: Waiting for application startup.
-<span style="color: green;">INFO</span>: Application startup complete.
-```
+ <span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server đ
-</div>
+ 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>
-/// note
+ <span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> đ main.py
-La commande `uvicorn main:app` fait référence à :
+ <span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
+ the following code:
-* `main` : le fichier `main.py` (le module Python).
-* `app` : l'objet créé dans `main.py` via la ligne `app = FastAPI()`.
-* `--reload` : l'option disant à uvicorn de redémarrer le serveur à chaque changement du code. à ne pas utiliser en production !
+ <u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
-///
+ <span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
+ <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
+ <b>fastapi run</b>
-Vous devriez voir dans la console, une ligne semblable Ă la suivante :
+ Logs:
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
+ <b>[</b><font color="#4E9A06">'/home/user/code/awesomeapp'</font><b>]</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
+ to quit<b>)</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
+```
+
+</div>
+
+Dans la sortie, il y a une ligne semblable Ă :
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
-Cette ligne montre l'URL par laquelle l'app est actuellement accessible, sur votre machine locale.
+Cette ligne montre lâURL oĂč votre application est servie, sur votre machine locale.
-### Allez voir le résultat
+### Vérifiez { #check-it }
-Ouvrez votre navigateur Ă l'adresse <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
+Ouvrez votre navigateur Ă lâadresse <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
-Vous obtiendrez cette réponse JSON :
+Vous verrez la réponse JSON suivante :
```JSON
{"message": "Hello World"}
```
-### Documentation interactive de l'API
+### Documentation interactive de lâAPI { #interactive-api-docs }
-Rendez-vous sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+Allez maintenant sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
-Vous verrez la documentation interactive de l'API générée automatiquement (via <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>) :
+Vous verrez la documentation interactive de lâAPI gĂ©nĂ©rĂ©e automatiquement (fournie par <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>) :

-### Documentation alternative
+### Documentation alternative de lâAPI { #alternative-api-docs }
-Ensuite, rendez-vous sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
+Et maintenant, allez sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
-Vous y verrez la documentation alternative (via <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :
+Vous verrez la documentation automatique alternative (fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :

-### OpenAPI
+### OpenAPI { #openapi }
-**FastAPI** génÚre un "schéma" contenant toute votre API dans le standard de définition d'API **OpenAPI**.
+**FastAPI** génÚre un « schéma » contenant toute votre API en utilisant le standard **OpenAPI** pour définir des API.
-#### "Schéma"
+#### « Schéma » { #schema }
-Un "schéma" est une définition ou une description de quelque chose. Pas le code qui l'implémente, uniquement une description abstraite.
+Un « schĂ©ma » est une dĂ©finition ou une description de quelque chose. Pas le code qui lâimplĂ©mente, mais uniquement une description abstraite.
-#### "Schéma" d'API
+#### « SchĂ©ma » dâAPI { #api-schema }
Ici, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> est une spécification qui dicte comment définir le schéma de votre API.
-Le schéma inclut les chemins de votre API, les paramÚtres potentiels de chaque chemin, etc.
-
-#### "Schéma" de données
+Cette dĂ©finition de schĂ©ma inclut les chemins de votre API, les paramĂštres possibles quâils prennent, etc.
-Le terme "schéma" peut aussi faire référence à la forme de la donnée, comme un contenu JSON.
+#### « Schéma » de données { #data-schema }
-Dans ce cas, cela signifierait les attributs JSON, ainsi que les types de ces attributs, etc.
+Le terme « schĂ©ma » peut Ă©galement faire rĂ©fĂ©rence Ă la forme dâune donnĂ©e, comme un contenu JSON.
-#### OpenAPI et JSON Schema
+Dans ce cas, cela désignerait les attributs JSON, ainsi que leurs types, etc.
-**OpenAPI** définit un schéma d'API pour votre API. Il inclut des définitions (ou "schémas") de la donnée envoyée et reçue par votre API en utilisant **JSON Schema**, le standard des schémas de données JSON.
+#### OpenAPI et JSON Schema { #openapi-and-json-schema }
-#### Allez voir `openapi.json`
+OpenAPI dĂ©finit un schĂ©ma dâAPI pour votre API. Et ce schĂ©ma inclut des dĂ©finitions (ou « schĂ©mas ») des donnĂ©es envoyĂ©es et reçues par votre API en utilisant **JSON Schema**, le standard pour les schĂ©mas de donnĂ©es JSON.
-Si vous ĂȘtes curieux d'Ă quoi ressemble le schĂ©ma brut **OpenAPI**, **FastAPI** gĂ©nĂšre automatiquement un (schĂ©ma) JSON avec les descriptions de toute votre API.
+#### Voir le `openapi.json` { #check-the-openapi-json }
-Vous pouvez le voir directement Ă cette adresse : <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
+Si vous ĂȘtes curieux de voir Ă quoi ressemble le schĂ©ma OpenAPI brut, FastAPI gĂ©nĂšre automatiquement un JSON (schĂ©ma) avec les descriptions de toute votre API.
-Le schéma devrait ressembler à ceci :
+Vous pouvez le voir directement Ă lâadresse : <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
+Il affichera un JSON commençant par quelque chose comme :
```JSON
{
- "openapi": "3.0.2",
+ "openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
...
```
-#### Ă quoi sert OpenAPI
+#### Ă quoi sert OpenAPI { #what-is-openapi-for }
-Le schéma **OpenAPI** est ce qui alimente les deux systÚmes de documentation interactive.
+Le schéma OpenAPI est ce qui alimente les deux systÚmes de documentation interactive inclus.
-Et il existe des dizaines d'alternatives, toutes basées sur **OpenAPI**. Vous pourriez facilement ajouter n'importe laquelle de ces alternatives à votre application **FastAPI**.
+Et il existe des dizaines dâalternatives, toutes basĂ©es sur OpenAPI. Vous pourriez facilement ajouter nâimporte laquelle de ces alternatives Ă votre application construite avec **FastAPI**.
-Vous pourriez aussi l'utiliser pour générer du code automatiquement, pour les clients qui communiquent avec votre API. Comme par exemple, des applications frontend, mobiles ou IOT.
+Vous pourriez Ă©galement lâutiliser pour gĂ©nĂ©rer du code automatiquement, pour les clients qui communiquent avec votre API. Par exemple, des applications frontend, mobiles ou IoT.
-## Récapitulatif, étape par étape
+### Déployer votre application (optionnel) { #deploy-your-app-optional }
-### Ătape 1 : import `FastAPI`
+Vous pouvez, si vous le souhaitez, dĂ©ployer votre application FastAPI sur <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, allez rejoindre la liste dâattente si ce nâest pas dĂ©jĂ fait. đ
-{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
+Si vous avez dĂ©jĂ un compte **FastAPI Cloud** (nous vous avons invitĂ© depuis la liste dâattente đ), vous pouvez dĂ©ployer votre application avec une seule commande.
-`FastAPI` est une classe Python qui fournit toutes les fonctionnalités nécessaires au lancement de votre API.
+Avant de dĂ©ployer, vous devez vous assurer que vous ĂȘtes connectĂ© :
-/// note | Détails techniques
-
-`FastAPI` est une classe héritant directement de `Starlette`.
-
-Vous pouvez donc aussi utiliser toutes les fonctionnalités de <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> depuis `FastAPI`.
-
-///
-
-### Ătape 2 : crĂ©er une "instance" `FastAPI`
+<div class="termy">
-{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
+```console
+$ fastapi login
-Ici la variable `app` sera une "instance" de la classe `FastAPI`.
+You are logged in to FastAPI Cloud đ
+```
-Ce sera le point principal d'interaction pour créer toute votre API.
+</div>
-Cette `app` est la mĂȘme que celle Ă laquelle fait rĂ©fĂ©rence `uvicorn` dans la commande :
+Puis déployez votre application :
<div class="termy">
```console
-$ uvicorn main:app --reload
+$ fastapi deploy
+
+Deploying to FastAPI Cloud...
+
+â
Deployment successful!
-<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+đ Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
-Si vous créez votre app avec :
+Câest tout ! Vous pouvez maintenant accĂ©der Ă votre application Ă cette URL. âš
-{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
+## Récapitulatif, étape par étape { #recap-step-by-step }
-Et la mettez dans un fichier `main.py`, alors vous appelleriez `uvicorn` avec :
+### Ătape 1 : importer `FastAPI` { #step-1-import-fastapi }
-<div class="termy">
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
-```console
-$ uvicorn main:my_awesome_api --reload
+`FastAPI` est une classe Python qui fournit toutes les fonctionnalités nécessaires à votre API.
-<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
+/// note | Détails techniques
-</div>
+`FastAPI` est une classe qui hérite directement de `Starlette`.
+
+Vous pouvez donc aussi utiliser toutes les fonctionnalités de <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> avec `FastAPI`.
+
+///
+
+### Ătape 2 : crĂ©er une « instance » `FastAPI` { #step-2-create-a-fastapi-instance }
+
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
+
+Ici, la variable `app` sera une « instance » de la classe `FastAPI`.
+
+Ce sera le point principal dâinteraction pour crĂ©er toute votre API.
-### Ătape 3: crĂ©er une *opĂ©ration de chemin*
+### Ătape 3 : crĂ©er un « chemin dâaccĂšs » { #step-3-create-a-path-operation }
-#### Chemin
+#### Chemin { #path }
-Chemin, ou "path" fait référence ici à la derniÚre partie de l'URL démarrant au premier `/`.
+« Chemin » fait ici rĂ©fĂ©rence Ă la derniĂšre partie de lâURL Ă partir du premier `/`.
-Donc, dans un URL tel que :
+Donc, dans une URL telle que :
```
https://example.com/items/foo
```
-...le "path" serait :
+... le chemin serait :
```
/items/foo
/// info
-Un chemin, ou "path" est aussi souvent appelé route ou "endpoint".
+Un « chemin » est aussi couramment appelé « endpoint » ou « route ».
///
-#### Opération
+Lors de la crĂ©ation dâune API, le « chemin » est la maniĂšre principale de sĂ©parer les « prĂ©occupations » et les « ressources ».
-"Opération" fait référence à une des "méthodes" HTTP.
+#### Opération { #operation }
-Une de :
+« OpĂ©ration » fait ici rĂ©fĂ©rence Ă lâune des « mĂ©thodes » HTTP.
+
+Lâune de :
* `POST`
* `GET`
* `PUT`
* `DELETE`
-...ou une des plus exotiques :
+... et les plus exotiques :
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
-Dans le protocol HTTP, vous pouvez communiquer avec chaque chemin en utilisant une (ou plus) de ces "méthodes".
+Dans le protocole HTTP, vous pouvez communiquer avec chaque chemin en utilisant une (ou plusieurs) de ces « méthodes ».
---
-En construisant des APIs, vous utilisez généralement ces méthodes HTTP spécifiques pour effectuer une action précise.
-
-Généralement vous utilisez :
+En construisant des APIs, vous utilisez normalement ces méthodes HTTP spécifiques pour effectuer une action précise.
-* `POST` : pour créer de la donnée.
-* `GET` : pour lire de la donnée.
-* `PUT` : pour mettre à jour de la donnée.
-* `DELETE` : pour supprimer de la donnée.
+En général, vous utilisez :
-Donc, dans **OpenAPI**, chaque méthode HTTP est appelée une "opération".
+* `POST` : pour créer des données.
+* `GET` : pour lire des données.
+* `PUT` : pour mettre à jour des données.
+* `DELETE` : pour supprimer des données.
-Nous allons donc aussi appeler ces derniÚres des "**opérations**".
+Donc, dans OpenAPI, chacune des méthodes HTTP est appelée une « opération ».
+Nous allons donc aussi les appeler « opérations ».
-#### Définir un *décorateur d'opération de chemin*
+#### DĂ©finir un « dĂ©corateur de chemin dâaccĂšs » { #define-a-path-operation-decorator }
-{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
-Le `@app.get("/")` dit Ă **FastAPI** que la fonction en dessous est chargĂ©e de gĂ©rer les requĂȘtes qui vont sur :
+Le `@app.get("/")` indique Ă **FastAPI** que la fonction juste en dessous est chargĂ©e de gĂ©rer les requĂȘtes qui vont versâŻ:
* le chemin `/`
-* en utilisant une <abbr title="une méthode GET HTTP">opération <code>get</code></abbr>
+* en utilisant une <abbr title="une méthode HTTP GET"><code>get</code> opération</abbr>
/// info | `@décorateur` Info
-Cette syntaxe `@something` en Python est appelée un "décorateur".
+Cette syntaxe `@something` en Python est appelée un « décorateur ».
-Vous la mettez au dessus d'une fonction. Comme un joli chapeau dĂ©coratif (j'imagine que ce terme vient de lĂ đ€·đ»ââ).
+Vous la mettez au-dessus dâune fonction. Comme un joli chapeau dĂ©coratif (jâimagine que câest de lĂ que vient le terme đ€·đ»ââ).
-Un "décorateur" prend la fonction en dessous et en fait quelque chose.
+Un « décorateur » prend la fonction en dessous et fait quelque chose avec.
-Dans notre cas, ce décorateur dit à **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec l'**opération** `get`.
+Dans notre cas, ce décorateur indique à **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec une **opération** `get`.
-C'est le "**décorateur d'opération de chemin**".
+Câest le « dĂ©corateur de chemin dâaccĂšs ».
///
* `@app.put()`
* `@app.delete()`
-Tout comme celles les plus exotiques :
+Ainsi que les plus exotiques :
* `@app.options()`
* `@app.head()`
/// tip | Astuce
-Vous ĂȘtes libres d'utiliser chaque opĂ©ration (mĂ©thode HTTP) comme vous le dĂ©sirez.
+Vous ĂȘtes libre dâutiliser chaque opĂ©ration (mĂ©thode HTTP) comme vous le souhaitez.
-**FastAPI** n'impose pas de sens spécifique à chacune d'elle.
+**FastAPI** nâimpose aucune signification spĂ©cifique.
-Les informations qui sont présentées ici forment une directive générale, pas des obligations.
+Les informations ici sont présentées comme des lignes directrices, pas comme une obligation.
-Par exemple, quand l'on utilise **GraphQL**, toutes les actions sont effectuées en utilisant uniquement des opérations `POST`.
+Par exemple, lorsque vous utilisez GraphQL, vous effectuez normalement toutes les actions en utilisant uniquement des opérations `POST`.
///
-### Ătape 4 : dĂ©finir la **fonction de chemin**.
+### Ătape 4 : dĂ©finir la **fonction de chemin dâaccĂšs** { #step-4-define-the-path-operation-function }
-Voici notre "**fonction de chemin**" (ou fonction d'opération de chemin) :
+Voici notre « fonction de chemin dâaccĂšs » :
* **chemin** : `/`.
* **opération** : `get`.
-* **fonction** : la fonction sous le "décorateur" (sous `@app.get("/")`).
+* **fonction** : la fonction sous le « décorateur » (sous `@app.get("/")`).
-{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
-C'est une fonction Python.
+Câest une fonction Python.
-Elle sera appelĂ©e par **FastAPI** quand une requĂȘte sur l'URL `/` sera reçue via une opĂ©ration `GET`.
+Elle sera appelĂ©e par **FastAPI** chaque fois quâil recevra une requĂȘte vers lâURL « / » en utilisant une opĂ©ration `GET`.
-Ici, c'est une fonction asynchrone (définie avec `async def`).
+Dans ce cas, câest une fonction `async`.
---
-Vous pourriez aussi la définir comme une fonction classique plutÎt qu'avec `async def` :
+Vous pouvez aussi la définir comme une fonction normale au lieu de `async def` :
-{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
+{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
/// note
-Si vous ne connaissez pas la diffĂ©rence, allez voir la section [Concurrence : *"Vous ĂȘtes pressĂ©s ?"*](../async.md#vous-etes-presses){.internal-link target=_blank}.
+Si vous ne connaissez pas la différence, consultez [Asynchrone : « Pressé ? »](../async.md#in-a-hurry){.internal-link target=_blank}.
///
-### Ătape 5 : retourner le contenu
+### Ătape 5 : retourner le contenu { #step-5-return-the-content }
+
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
+
+Vous pouvez retourner un `dict`, une `list`, des valeurs uniques comme `str`, `int`, etc.
+
+Vous pouvez également retourner des modÚles Pydantic (vous en verrez plus à ce sujet plus tard).
+
+Il existe de nombreux autres objets et modĂšles qui seront automatiquement convertis en JSON (y compris des ORM, etc.). Essayez dâutiliser vos favoris, il est fort probable quâils soient dĂ©jĂ pris en charge.
+
+### Ătape 6 : le dĂ©ployer { #step-6-deploy-it }
+
+DĂ©ployez votre application sur **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** avec une seule commande : `fastapi deploy`. đ
+
+#### Ă propos de FastAPI Cloud { #about-fastapi-cloud }
+
+**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** est construit par le mĂȘme auteur et lâĂ©quipe derriĂšre **FastAPI**.
+
+Il simplifie le processus de **construction**, de **dĂ©ploiement** et dâ**accĂšs** Ă une API avec un minimum dâeffort.
+
+Il apporte la mĂȘme **expĂ©rience dĂ©veloppeur** de crĂ©ation dâapplications avec FastAPI au **dĂ©ploiement** dans le cloud. đ
-{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
+FastAPI Cloud est le sponsor principal et le financeur des projets open source *FastAPI and friends*. âš
-Vous pouvez retourner un dictionnaire (`dict`), une liste (`list`), des valeurs seules comme des chaines de caractĂšres (`str`) et des entiers (`int`), etc.
+#### DĂ©ployer sur dâautres fournisseurs cloud { #deploy-to-other-cloud-providers }
-Vous pouvez aussi retourner des models **Pydantic** (qui seront détaillés plus tard).
+FastAPI est open source et basĂ© sur des standards. Vous pouvez dĂ©ployer des applications FastAPI chez nâimporte quel fournisseur cloud de votre choix.
-Il y a de nombreux autres objets et modÚles qui seront automatiquement convertis en JSON. Essayez d'utiliser vos favoris, il est fort probable qu'ils soient déjà supportés.
+Suivez les guides de votre fournisseur cloud pour y dĂ©ployer des applications FastAPI. đ€
-## Récapitulatif
+## Récapitulatif { #recap }
* Importez `FastAPI`.
-* Créez une instance d'`app`.
-* Ajoutez une **décorateur d'opération de chemin** (tel que `@app.get("/")`).
-* Ajoutez une **fonction de chemin** (telle que `def root(): ...` comme ci-dessus).
-* Lancez le serveur de développement (avec `uvicorn main:app --reload`).
+* Créez une instance `app`.
+* Ăcrivez un **dĂ©corateur de chemin dâaccĂšs** avec des dĂ©corateurs comme `@app.get("/")`.
+* DĂ©finissez une **fonction de chemin dâaccĂšs** ; par exemple, `def root(): ...`.
+* Exécutez le serveur de développement avec la commande `fastapi dev`.
+* Déployez éventuellement votre application avec `fastapi deploy`.
-# Tutoriel - Guide utilisateur - Introduction
+# Tutoriel - Guide utilisateur { #tutorial-user-guide }
Ce tutoriel vous montre comment utiliser **FastAPI** avec la plupart de ses fonctionnalités, étape par étape.
-Chaque section s'appuie progressivement sur les précédentes, mais elle est structurée de maniÚre à séparer les sujets, afin que vous puissiez aller directement à l'un d'entre eux pour résoudre vos besoins spécifiques en matiÚre d'API.
+Chaque section s'appuie progressivement sur les précédentes, mais elle est structurée de maniÚre à séparer les sujets, afin que vous puissiez aller directement à l'un d'entre eux pour répondre à vos besoins spécifiques d'API.
-Il est également conçu pour fonctionner comme une référence future.
+Il est également conçu pour servir de référence ultérieure, afin que vous puissiez revenir voir exactement ce dont vous avez besoin.
-Vous pouvez donc revenir et voir exactement ce dont vous avez besoin.
-
-## Exécuter le code
+## Exécuter le code { #run-the-code }
Tous les blocs de code peuvent ĂȘtre copiĂ©s et utilisĂ©s directement (il s'agit en fait de fichiers Python testĂ©s).
-Pour exécuter l'un de ces exemples, copiez le code dans un fichier `main.py`, et commencez `uvicorn` avec :
+Pour exécuter l'un de ces exemples, copiez le code dans un fichier `main.py`, et démarrez `fastapi dev` avec :
<div class="termy">
```console
-$ uvicorn main:app --reload
+$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
+
+ <span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server đ
+
+ Searching for package file structure from directories
+ with <font color="#3465A4">__init__.py</font> files
+ Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> đ main.py
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
+ the following code:
+
+ <u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
+ <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
+ <b>fastapi run</b>
-<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-<span style="color: green;">INFO</span>: Started reloader process [28720]
-<span style="color: green;">INFO</span>: Started server process [28722]
-<span style="color: green;">INFO</span>: Waiting for application startup.
-<span style="color: green;">INFO</span>: Application startup complete.
+ Logs:
+
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
+ <b>[</b><font color="#4E9A06">'/home/user/code/awesomeapp'</font><b>]</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C
+ to quit<b>)</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
+ <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
---
-## Installer FastAPI
+## Installer FastAPI { #install-fastapi }
La premiÚre étape consiste à installer FastAPI.
-Pour le tutoriel, vous voudrez peut-ĂȘtre l'installer avec toutes les dĂ©pendances et fonctionnalitĂ©s optionnelles :
+Assurez-vous de créer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis **d'installer FastAPI** :
<div class="termy">
```console
-$ pip install fastapi[all]
+$ pip install "fastapi[standard]"
---> 100%
```
</div>
-... qui comprend également `uvicorn`, que vous pouvez utiliser comme serveur pour exécuter votre code.
-
-/// note
-
-Vous pouvez également l'installer piÚce par piÚce.
+/// note | Remarque
-C'est ce que vous feriez probablement une fois que vous voudrez déployer votre application en production :
+Lorsque vous installez avec `pip install "fastapi[standard]"` cela inclut des dépendances standard optionnelles par défaut, y compris `fastapi-cloud-cli`, qui vous permet de déployer sur <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
-```
-pip install fastapi
-```
-
-Installez également `uvicorn` pour qu'il fonctionne comme serveur :
-
-```
-pip install uvicorn
-```
+Si vous ne souhaitez pas avoir ces dépendances optionnelles, vous pouvez à la place installer `pip install fastapi`.
-Et la mĂȘme chose pour chacune des dĂ©pendances facultatives que vous voulez utiliser.
+Si vous souhaitez installer les dépendances standard mais sans `fastapi-cloud-cli`, vous pouvez installer avec `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
///
-## Guide utilisateur avancé
+## Guide d'utilisation avancé { #advanced-user-guide }
Il existe également un **Guide d'utilisation avancé** que vous pouvez lire plus tard aprÚs ce **Tutoriel - Guide d'utilisation**.
-# ParamÚtres de chemin et validations numériques
+# ParamÚtres de chemin et validations numériques { #path-parameters-and-numeric-validations }
De la mĂȘme façon que vous pouvez dĂ©clarer plus de validations et de mĂ©tadonnĂ©es pour les paramĂštres de requĂȘte avec `Query`, vous pouvez dĂ©clarer le mĂȘme type de validations et de mĂ©tadonnĂ©es pour les paramĂštres de chemin avec `Path`.
-## Importer Path
+## Importer `Path` { #import-path }
Tout d'abord, importez `Path` de `fastapi`, et importez `Annotated` :
Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant d'utiliser `Annotated`.
-Assurez-vous de [Mettre Ă jour la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} Ă la version 0.95.1 Ă minima avant d'utiliser `Annotated`.
+Assurez-vous de [Mettre Ă niveau la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} Ă la version 0.95.1 Ă minima avant d'utiliser `Annotated`.
///
-## Déclarer des métadonnées
+## Déclarer des métadonnées { #declare-metadata }
Vous pouvez dĂ©clarer les mĂȘmes paramĂštres que pour `Query`.
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
-/// note
+/// note | Remarque
Un paramĂštre de chemin est toujours requis car il doit faire partie du chemin. MĂȘme si vous l'avez dĂ©clarĂ© avec `None` ou dĂ©fini une valeur par dĂ©faut, cela ne changerait rien, il serait toujours requis.
///
-## Ordonnez les paramĂštres comme vous le souhaitez
+## Ordonner les paramĂštres comme vous le souhaitez { #order-the-parameters-as-you-need }
-/// tip
+/// tip | Astuce
Ce n'est probablement pas aussi important ou nécessaire si vous utilisez `Annotated`.
Mais vous avez toujours besoin d'utiliser `Path` pour le paramĂštre de chemin `item_id`. Et vous ne voulez pas utiliser `Annotated` pour une raison quelconque.
-Python se plaindra si vous mettez une valeur avec une "défaut" avant une valeur qui n'a pas de "défaut".
+Python se plaindra si vous mettez une valeur avec une « valeur par défaut » avant une valeur qui n'a pas de « valeur par défaut ».
Mais vous pouvez les rĂ©organiser, et avoir la valeur sans dĂ©faut (le paramĂštre de requĂȘte `q`) en premier.
Ainsi, vous pouvez déclarer votre fonction comme suit :
-{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
Mais gardez à l'esprit que si vous utilisez `Annotated`, vous n'aurez pas ce problÚme, cela n'aura pas d'importance car vous n'utilisez pas les valeurs par défaut des paramÚtres de fonction pour `Query()` ou `Path()`.
-{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py hl[10] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
-## Ordonnez les paramĂštres comme vous le souhaitez (astuces)
+## Ordonner les paramĂštres comme vous le souhaitez, astuces { #order-the-parameters-as-you-need-tricks }
-/// tip
+/// tip | Astuce
Ce n'est probablement pas aussi important ou nécessaire si vous utilisez `Annotated`.
* les avoir dans un ordre différent
* ne pas utiliser `Annotated`
-...Python a une petite syntaxe spéciale pour cela.
+... Python a une petite syntaxe spéciale pour cela.
Passez `*`, comme premier paramĂštre de la fonction.
Python ne fera rien avec ce `*`, mais il saura que tous les paramĂštres suivants doivent ĂȘtre appelĂ©s comme arguments "mots-clĂ©s" (paires clĂ©-valeur), Ă©galement connus sous le nom de <abbr title="De : K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. MĂȘme s'ils n'ont pas de valeur par dĂ©faut.
-{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
+{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
-# Avec `Annotated`
+### Mieux avec `Annotated` { #better-with-annotated }
Gardez à l'esprit que si vous utilisez `Annotated`, comme vous n'utilisez pas les valeurs par défaut des paramÚtres de fonction, vous n'aurez pas ce problÚme, et vous n'aurez probablement pas besoin d'utiliser `*`.
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
-## Validations numériques : supérieur ou égal
+## Validations numériques : supérieur ou égal { #number-validations-greater-than-or-equal }
Avec `Query` et `Path` (et d'autres que vous verrez plus tard) vous pouvez déclarer des contraintes numériques.
-Ici, avec `ge=1`, `item_id` devra ĂȘtre un nombre entier "`g`reater than or `e`qual" Ă `1`.
+Ici, avec `ge=1`, `item_id` devra ĂȘtre un nombre entier « `g`reater than or `e`qual » Ă `1`.
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
-## Validations numériques : supérieur ou égal et inférieur ou égal
-
-La mĂȘme chose s'applique pour :
-
-* `gt` : `g`reater `t`han
-* `le` : `l`ess than or `e`qual
-
-{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
-
-## Validations numériques : supérieur et inférieur ou égal
+## Validations numériques : supérieur et inférieur ou égal { #number-validations-greater-than-and-less-than-or-equal }
La mĂȘme chose s'applique pour :
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
-## Validations numériques : flottants, supérieur et inférieur
+## Validations numériques : flottants, supérieur et inférieur { #number-validations-floats-greater-than-and-less-than }
Les validations numériques fonctionnent également pour les valeurs `float`.
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
-## Pour résumer
+## Pour résumer { #recap }
Avec `Query`, `Path` (et d'autres que vous verrez plus tard) vous pouvez dĂ©clarer des mĂ©tadonnĂ©es et des validations de chaĂźnes de la mĂȘme maniĂšre qu'avec les [ParamĂštres de requĂȘte et validations de chaĂźnes](query-params-str-validations.md){.internal-link target=_blank}.
-# ParamĂštres de chemin
+# ParamĂštres de chemin { #path-parameters }
-Vous pouvez dĂ©clarer des "paramĂštres" ou "variables" de chemin avec la mĂȘme syntaxe que celle utilisĂ©e par le
-<a href="https://docs.python.org/fr/3/library/string.html#format-string-syntax" class="external-link" target="_blank">formatage de chaĂźne Python</a> :
+Vous pouvez dĂ©clarer des « paramĂštres » ou « variables » de chemin avec la mĂȘme syntaxe utilisĂ©e par les chaĂźnes de format Python :
+{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
-{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
+La valeur du paramĂštre de chemin `item_id` sera transmise Ă votre fonction dans l'argument `item_id`.
-La valeur du paramĂštre `item_id` sera transmise Ă la fonction dans l'argument `item_id`.
-
-Donc, si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>,
-vous verrez comme réponse :
+Donc, si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, vous verrez comme réponse :
```JSON
{"item_id":"foo"}
```
-## ParamÚtres de chemin typés
-
-Vous pouvez déclarer le type d'un paramÚtre de chemin dans la fonction, en utilisant les annotations de type Python :
+## ParamÚtres de chemin typés { #path-parameters-with-types }
+Vous pouvez déclarer le type d'un paramÚtre de chemin dans la fonction, en utilisant les annotations de type Python standard :
-{* ../../docs_src/path_params/tutorial002.py hl[7] *}
+{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
Ici, `item_id` est déclaré comme `int`.
-/// check | vérifier
+/// check | Vérifications
-Ceci vous permettra d'obtenir des fonctionnalités de l'éditeur dans votre fonction, telles
-que des vérifications d'erreur, de l'auto-complétion, etc.
+Cela vous apporte la prise en charge par l'éditeur dans votre fonction, avec vérifications d'erreurs, autocomplétion, etc.
///
-## <abbr title="aussi appelé sérialisation, ou parfois parsing ou marshalling en anglais">Conversion</abbr> de données
+## <abbr title="également appelé : sérialisation, parsing, marshalling">Conversion</abbr> de données { #data-conversion }
-Si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, vous aurez comme réponse :
+Si vous exécutez cet exemple et ouvrez votre navigateur sur <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, vous verrez comme réponse :
```JSON
{"item_id":3}
```
-/// check | vérifier
+/// check | Vérifications
-Comme vous l'avez remarqué, la valeur reçue par la fonction (et renvoyée ensuite) est `3`,
-en tant qu'entier (`int`) Python, pas la chaĂźne de caractĂšres (`string`) `"3"`.
+Remarquez que la valeur reçue par votre fonction (et renvoyée) est `3`, en tant qu'entier (`int`) Python, pas la chaßne de caractÚres « 3 ».
-Grùce aux déclarations de types, **FastAPI** fournit du
-<abbr title="conversion de la chaĂźne de caractĂšres venant de la requĂȘte HTTP en donnĂ©es Python">"parsing"</abbr> automatique.
+Ainsi, avec cette dĂ©claration de type, **FastAPI** vous fournit automatiquement le <abbr title="conversion de la chaĂźne de caractĂšres provenant d'une requĂȘte HTTP en donnĂ©es Python">« parsing »</abbr> de la requĂȘte.
///
-## Validation de données
+## Validation de données { #data-validation }
-Si vous allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, vous aurez une belle erreur HTTP :
+Mais si vous allez dans le navigateur sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, vous verrez une belle erreur HTTP :
```JSON
{
- "detail": [
- {
- "loc": [
- "path",
- "item_id"
- ],
- "msg": "value is not a valid integer",
- "type": "type_error.integer"
- }
- ]
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "foo"
+ }
+ ]
}
```
-car le paramĂštre de chemin `item_id` possĂšde comme valeur `"foo"`, qui ne peut pas ĂȘtre convertie en entier (`int`).
-
-La mĂȘme erreur se produira si vous passez un nombre flottant (`float`) et non un entier, comme ici
-<a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>.
+car le paramÚtre de chemin `item_id` a pour valeur « foo », qui n'est pas un `int`.
+La mĂȘme erreur apparaĂźtrait si vous fournissiez un `float` au lieu d'un `int`, comme ici : <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
-/// check | vérifier
+/// check | Vérifications
-Donc, avec ces mĂȘmes dĂ©clarations de type Python, **FastAPI** vous fournit de la validation de donnĂ©es.
+Ainsi, avec la mĂȘme dĂ©claration de type Python, **FastAPI** vous fournit la validation de donnĂ©es.
-Notez que l'erreur mentionne le point exact oĂč la validation n'a pas rĂ©ussi.
+Remarquez que l'erreur indique clairement l'endroit exact oĂč la validation n'a pas rĂ©ussi.
-Ce qui est incroyablement utile au moment de développer et débugger du code qui interagit avec votre API.
+C'est incroyablement utile lors du développement et du débogage du code qui interagit avec votre API.
///
-## Documentation
+## Documentation { #documentation }
-Et quand vous vous rendez sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, vous verrez la
-documentation générée automatiquement et interactive :
+Et lorsque vous ouvrez votre navigateur sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, vous verrez une documentation d'API automatique et interactive comme :
<img src="/img/tutorial/path-params/image01.png">
-/// info
+/// check | Vérifications
-à nouveau, en utilisant uniquement les déclarations de type Python, **FastAPI** vous fournit automatiquement une documentation interactive (via Swagger UI).
+Ă nouveau, simplement avec cette mĂȘme dĂ©claration de type Python, **FastAPI** vous fournit une documentation interactive automatique (intĂ©grant Swagger UI).
-On voit bien dans la documentation que `item_id` est déclaré comme entier.
+Remarquez que le paramÚtre de chemin est déclaré comme entier.
///
-## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative.
+## Les avantages d'une norme, documentation alternative { #standards-based-benefits-alternative-documentation }
-Le schéma généré suivant la norme <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a>,
-il existe de nombreux outils compatibles.
+Et comme le schéma généré suit la norme <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a>, il existe de nombreux outils compatibles.
-GrĂące Ă cela, **FastAPI** lui-mĂȘme fournit une documentation alternative (utilisant ReDoc), qui peut ĂȘtre lue
-sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> :
+GrĂące Ă cela, **FastAPI** fournit lui-mĂȘme une documentation d'API alternative (utilisant ReDoc), accessible sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> :
<img src="/img/tutorial/path-params/image02.png">
-De la mĂȘme façon, il existe bien d'autres outils compatibles, y compris des outils de gĂ©nĂ©ration de code
-pour de nombreux langages.
+De la mĂȘme façon, il existe de nombreux outils compatibles, y compris des outils de gĂ©nĂ©ration de code pour de nombreux langages.
-## Pydantic
+## Pydantic { #pydantic }
-Toute la validation de données est effectué en arriÚre-plan avec <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>,
-dont vous bĂ©nĂ©ficierez de tous les avantages. Vous savez donc que vous ĂȘtes entre de bonnes mains.
+Toute la validation de donnĂ©es est effectuĂ©e sous le capot par <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, vous en bĂ©nĂ©ficiez donc pleinement. Vous savez ainsi que vous ĂȘtes entre de bonnes mains.
-## L'ordre importe
+Vous pouvez utiliser les mĂȘmes dĂ©clarations de type avec `str`, `float`, `bool` et de nombreux autres types de donnĂ©es complexes.
-Quand vous crĂ©ez des *fonctions de chemins*, vous pouvez vous retrouver dans une situation oĂč vous avez un chemin fixe.
+Plusieurs d'entre eux sont explorés dans les prochains chapitres du tutoriel.
-Tel que `/users/me`, disons pour récupérer les données sur l'utilisateur actuel.
+## L'ordre importe { #order-matters }
-Et vous avez un second chemin : `/users/{user_id}` pour récupérer de la donnée sur un utilisateur spécifique grùce à son identifiant d'utilisateur
+Quand vous créez des *chemins d'accÚs*, vous pouvez vous retrouver dans une situation avec un chemin fixe.
-Les *fonctions de chemin* étant évaluées dans l'ordre, il faut s'assurer que la fonction correspondant à `/users/me` est déclarée avant celle de `/users/{user_id}` :
+Par exemple `/users/me`, disons pour récupérer les données de l'utilisateur actuel.
-{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
+Et vous pouvez aussi avoir un chemin `/users/{user_id}` pour récupérer des données sur un utilisateur spécifique grùce à un identifiant d'utilisateur.
-Sinon, le chemin `/users/{user_id}` correspondrait aussi à `/users/me`, la fonction "croyant" qu'elle a reçu un paramÚtre `user_id` avec pour valeur `"me"`.
+Comme les *chemins d'accÚs* sont évalués dans l'ordre, vous devez vous assurer que le chemin `/users/me` est déclaré avant celui de `/users/{user_id}` :
-## Valeurs prédéfinies
+{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
-Si vous avez une *fonction de chemin* qui reçoit un *paramÚtre de chemin*, mais que vous voulez que les valeurs possibles des paramÚtres soient prédéfinies, vous pouvez utiliser les <abbr title="Enumeration">`Enum`</abbr> de Python.
+Sinon, le chemin `/users/{user_id}` correspondrait aussi à `/users/me`, « pensant » qu'il reçoit un paramÚtre `user_id` avec la valeur « me ».
-### Création d'un `Enum`
+De mĂȘme, vous ne pouvez pas redĂ©finir un chemin d'accĂšs :
-Importez `Enum` et créez une sous-classe qui hérite de `str` et `Enum`.
+{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
-En hĂ©ritant de `str` la documentation sera capable de savoir que les valeurs doivent ĂȘtre de type `string` et pourra donc afficher cette `Enum` correctement.
+Le premier sera toujours utilisé puisque le chemin correspond en premier.
-Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs autorisées pour cette énumération.
+## Valeurs prédéfinies { #predefined-values }
-{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
+Si vous avez un *chemin d'accÚs* qui reçoit un *paramÚtre de chemin*, mais que vous voulez que les valeurs possibles de ce *paramÚtre de chemin* soient prédéfinies, vous pouvez utiliser une <abbr title="Enumeration">`Enum`</abbr> Python standard.
-/// info
+### Créer une classe `Enum` { #create-an-enum-class }
-<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Les énumérations (ou enums) sont disponibles en Python</a> depuis la version 3.4.
+Importez `Enum` et créez une sous-classe qui hérite de `str` et de `Enum`.
-///
+En hĂ©ritant de `str`, la documentation de l'API saura que les valeurs doivent ĂȘtre de type `string` et pourra donc s'afficher correctement.
+
+Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs valides disponibles :
+
+{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
/// tip | Astuce
-Pour ceux qui se demandent, "AlexNet", "ResNet", et "LeNet" sont juste des noms de <abbr title="Techniquement, des architectures de modĂšles">modĂšles</abbr> de Machine Learning.
+Si vous vous demandez, « AlexNet », « ResNet » et « LeNet » sont juste des noms de <abbr title="Techniquement, architectures de modÚles de Deep Learning">modÚles</abbr> de Machine Learning.
///
-### Déclarer un paramÚtre de chemin
+### Déclarer un paramÚtre de chemin { #declare-a-path-parameter }
-Créez ensuite un *paramÚtre de chemin* avec une annotation de type désignant l'énumération créée précédemment (`ModelName`) :
+Créez ensuite un *paramÚtre de chemin* avec une annotation de type utilisant la classe d'énumération que vous avez créée (`ModelName`) :
-{* ../../docs_src/path_params/tutorial005.py hl[16] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
-### Documentation
+### Consulter la documentation { #check-the-docs }
-Les valeurs disponibles pour le *paramÚtre de chemin* sont bien prédéfinies, la documentation les affiche correctement :
+Comme les valeurs disponibles pour le *paramÚtre de chemin* sont prédéfinies, la documentation interactive peut les afficher clairement :
<img src="/img/tutorial/path-params/image03.png">
-### Manipuler les *énumérations* Python
+### Travailler avec les *énumérations* Python { #working-with-python-enumerations }
-La valeur du *paramÚtre de chemin* sera un des "membres" de l'énumération.
+La valeur du *paramÚtre de chemin* sera un *membre d'énumération*.
-#### Comparer les *membres d'énumération*
+#### Comparer des *membres d'énumération* { #compare-enumeration-members }
-Vous pouvez comparer ce paramÚtre avec les membres de votre énumération `ModelName` :
+Vous pouvez le comparer avec le *membre d'énumération* dans votre enum `ModelName` :
-{* ../../docs_src/path_params/tutorial005.py hl[17] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
-#### Récupérer la *valeur de l'énumération*
+#### Obtenir la *valeur de l'énumération* { #get-the-enumeration-value }
-Vous pouvez obtenir la valeur réel d'un membre (une chaßne de caractÚres ici), avec `model_name.value`, ou en général, `votre_membre_d'enum.value` :
+Vous pouvez obtenir la valeur réelle (une `str` dans ce cas) avec `model_name.value`, ou en général, `votre_membre_d_enum.value` :
-{* ../../docs_src/path_params/tutorial005.py hl[20] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
/// tip | Astuce
-Vous pouvez aussi accéder la valeur `"lenet"` avec `ModelName.lenet.value`.
+Vous pouvez aussi accéder à la valeur « lenet » avec `ModelName.lenet.value`.
///
-#### Retourner des *membres d'énumération*
+#### Retourner des *membres d'énumération* { #return-enumeration-members }
-Vous pouvez retourner des *membres d'Ă©numĂ©ration* dans vos *fonctions de chemin*, mĂȘme imbriquĂ©e dans un JSON (e.g. un `dict`).
+Vous pouvez retourner des *membres d'Ă©numĂ©ration* depuis votre *chemin d'accĂšs*, mĂȘme imbriquĂ©s dans un corps JSON (par ex. un `dict`).
-Ils seront convertis vers leurs valeurs correspondantes (chaĂźnes de caractĂšres ici) avant d'ĂȘtre transmis au client :
+Ils seront convertis vers leurs valeurs correspondantes (des chaĂźnes de caractĂšres ici) avant d'ĂȘtre renvoyĂ©s au client :
-{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
+{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
-Le client recevra une réponse JSON comme celle-ci :
+Dans votre client, vous recevrez une réponse JSON comme :
```JSON
{
}
```
-## ParamĂštres de chemin contenant des chemins
+## ParamĂštres de chemin contenant des chemins { #path-parameters-containing-paths }
-Disons que vous avez une *fonction de chemin* liée au chemin `/files/{file_path}`.
+Disons que vous avez un *chemin d'accĂšs* avec un chemin `/files/{file_path}`.
-Mais que `file_path` lui-mĂȘme doit contenir un *chemin*, comme `home/johndoe/myfile.txt` par exemple.
+Mais vous avez besoin que `file_path` lui-mĂȘme contienne un *chemin*, comme `home/johndoe/myfile.txt`.
-Donc, l'URL pour ce fichier pourrait ĂȘtre : `/files/home/johndoe/myfile.txt`.
+Ainsi, l'URL pour ce fichier serait : `/files/home/johndoe/myfile.txt`.
-### Support d'OpenAPI
+### Support d'OpenAPI { #openapi-support }
-OpenAPI ne supporte pas de maniÚre de déclarer un paramÚtre de chemin contenant un *chemin*, cela pouvant causer des scénarios difficiles à tester et définir.
+OpenAPI ne prend pas en charge une maniÚre de déclarer un *paramÚtre de chemin* contenant un *chemin* à l'intérieur, car cela peut conduire à des scénarios difficiles à tester et à définir.
-Néanmoins, cela reste faisable dans **FastAPI**, via les outils internes de Starlette.
+Néanmoins, vous pouvez toujours le faire dans **FastAPI**, en utilisant l'un des outils internes de Starlette.
-Et la documentation fonctionne quand mĂȘme, bien qu'aucune section ne soit ajoutĂ©e pour dire que la paramĂštre devrait contenir un *chemin*.
+Et la documentation fonctionnera quand mĂȘme, mĂȘme si aucune indication supplĂ©mentaire ne sera ajoutĂ©e pour dire que le paramĂštre doit contenir un chemin.
-### Convertisseur de *chemin*
+### Convertisseur de chemin { #path-convertor }
-En utilisant une option de Starlette directement, vous pouvez déclarer un *paramÚtre de chemin* contenant un *chemin* avec une URL comme :
+En utilisant une option directement depuis Starlette, vous pouvez déclarer un *paramÚtre de chemin* contenant un *chemin* avec une URL comme :
```
/files/{file_path:path}
```
-Dans ce cas, le nom du paramĂštre est `file_path`, et la derniĂšre partie, `:path`, indique Ă Starlette que le paramĂštre devrait correspondre Ă un *chemin*.
+Dans ce cas, le nom du paramĂštre est `file_path`, et la derniĂšre partie, `:path`, indique que le paramĂštre doit correspondre Ă n'importe quel *chemin*.
-Vous pouvez donc l'utilisez comme tel :
+Vous pouvez donc l'utiliser ainsi :
-{* ../../docs_src/path_params/tutorial004.py hl[6] *}
+{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
/// tip | Astuce
-Vous pourriez avoir besoin que le paramÚtre contienne `/home/johndoe/myfile.txt`, avec un slash au début (`/`).
+Vous pourriez avoir besoin que le paramĂštre contienne `/home/johndoe/myfile.txt`, avec un slash initial (`/`).
Dans ce cas, l'URL serait : `/files//home/johndoe/myfile.txt`, avec un double slash (`//`) entre `files` et `home`.
///
-## Récapitulatif
+## Récapitulatif { #recap }
-Avec **FastAPI**, en utilisant les déclarations de type rapides, intuitives et standards de Python, vous bénéficiez de :
+Avec **FastAPI**, en utilisant des déclarations de type Python courtes, intuitives et standard, vous obtenez :
-* Support de l'éditeur : vérification d'erreurs, auto-complétion, etc.
-* <abbr title="conversion de la chaĂźne de caractĂšres venant de la requĂȘte HTTP en donnĂ©es Python">"Parsing"</abbr> de donnĂ©es.
-* Validation de données.
-* Annotations d'API et documentation automatique.
+* Support de l'éditeur : vérifications d'erreurs, autocomplétion, etc.
+* DonnĂ©es « <abbr title="conversion de la chaĂźne de caractĂšres provenant d'une requĂȘte HTTP en donnĂ©es Python">parsing</abbr> »
+* Validation de données
+* Annotations d'API et documentation automatique
-Et vous n'avez besoin de le déclarer qu'une fois.
+Et vous n'avez besoin de les déclarer qu'une seule fois.
-C'est probablement l'avantage visible principal de **FastAPI** comparé aux autres *frameworks* (outre les performances pures).
+C'est probablement l'avantage visible principal de **FastAPI** comparé aux autres frameworks (outre les performances pures).
-# ParamĂštres de requĂȘte et validations de chaĂźnes de caractĂšres
+# ParamĂštres de requĂȘte et validations de chaĂźnes de caractĂšres { #query-parameters-and-string-validations }
-**FastAPI** vous permet de dĂ©clarer des informations et des validateurs additionnels pour vos paramĂštres de requĂȘtes.
+**FastAPI** vous permet de déclarer des informations et des validations supplémentaires pour vos paramÚtres.
-Commençons avec cette application pour exemple :
+Prenons cette application comme exemple :
-{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
-Le paramĂštre de requĂȘte `q` a pour type `Union[str, None]` (ou `str | None` en Python 3.10), signifiant qu'il est de type `str` mais pourrait aussi ĂȘtre Ă©gal Ă `None`, et bien sĂ»r, la valeur par dĂ©faut est `None`, donc **FastAPI** saura qu'il n'est pas requis.
+Le paramĂštre de requĂȘte `q` est de type `str | None`, cela signifie quâil est de type `str` mais peut aussi ĂȘtre `None`, et en effet, la valeur par dĂ©faut est `None`, donc FastAPI saura quâil nâest pas requis.
-/// note
+/// note | Remarque
-**FastAPI** saura que la valeur de `q` n'est pas requise grùce à la valeur par défaut `= None`.
+FastAPI saura que la valeur de `q` nâest pas requise grĂące Ă la valeur par dĂ©faut `= None`.
-Le `Union` dans `Union[str, None]` permettra à votre éditeur de vous offrir un meilleur support et de détecter les erreurs.
+Avoir `str | None` permettra à votre éditeur de vous offrir un meilleur support et de détecter les erreurs.
///
-## Validation additionnelle
+## Validation additionnelle { #additional-validation }
-Nous allons imposer que bien que `q` soit un paramĂštre optionnel, dĂšs qu'il est fourni, **sa longueur n'excĂšde pas 50 caractĂšres**.
+Nous allons imposer que, mĂȘme si `q` est optionnel, dĂšs quâil est fourni, **sa longueur nâexcĂšde pas 50 caractĂšres**.
-## Importer `Query`
+### Importer `Query` et `Annotated` { #import-query-and-annotated }
-Pour cela, importez d'abord `Query` depuis `fastapi` :
+Pour ce faire, importez dâabord :
-{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *}
+- `Query` depuis `fastapi`
+- `Annotated` depuis `typing`
-## Utiliser `Query` comme valeur par défaut
+{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
-Construisez ensuite la valeur par défaut de votre paramÚtre avec `Query`, en choisissant 50 comme `max_length` :
+/// info
-{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *}
+FastAPI a ajouté la prise en charge de `Annotated` (et a commencé à le recommander) dans la version 0.95.0.
-Comme nous devons remplacer la valeur par dĂ©faut `None` dans la fonction par `Query()`, nous pouvons maintenant dĂ©finir la valeur par dĂ©faut avec le paramĂštre `Query(default=None)`, il sert le mĂȘme objectif qui est de dĂ©finir cette valeur par dĂ©faut.
+Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant dâutiliser `Annotated`.
-Donc :
+Assurez-vous de [mettre Ă niveau la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} vers au moins 0.95.1 avant dâutiliser `Annotated`.
+
+///
+
+## Utiliser `Annotated` dans le type pour le paramĂštre `q` { #use-annotated-in-the-type-for-the-q-parameter }
+
+Vous vous souvenez que je vous ai dit plus tĂŽt que `Annotated` peut ĂȘtre utilisĂ© pour ajouter des mĂ©tadonnĂ©es Ă vos paramĂštres dans lâ[Introduction aux types Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} ?
+
+Câest le moment de lâutiliser avec FastAPI. đ
+
+Nous avions cette annotation de type :
+
+//// tab | Python 3.10+
```Python
-q: Union[str, None] = Query(default=None)
+q: str | None = None
```
-... rend le paramÚtre optionnel, et est donc équivalent à :
+////
+
+//// tab | Python 3.9+
```Python
q: Union[str, None] = None
```
-Mais dĂ©clare explicitement `q` comme Ă©tant un paramĂštre de requĂȘte.
+////
-/// info
+Ce que nous allons faire, câest lâenglober avec `Annotated`, de sorte que cela devienne :
-Gardez Ă l'esprit que la partie la plus importante pour rendre un paramĂštre optionnel est :
+//// tab | Python 3.10+
```Python
-= None
+q: Annotated[str | None] = None
```
-ou :
+////
+
+//// tab | Python 3.9+
```Python
-= Query(None)
+q: Annotated[Union[str, None]] = None
```
-et utilisera ce `None` pour dĂ©tecter que ce paramĂštre de requĂȘte **n'est pas requis**.
+////
+
+Les deux versions signifient la mĂȘme chose, `q` est un paramĂštre qui peut ĂȘtre une `str` ou `None`, et par dĂ©faut, câest `None`.
+
+Passons maintenant aux choses amusantes. đ
-Le `Union[str, None]` est uniquement là pour permettre à votre éditeur un meilleur support.
+## Ajouter `Query` Ă `Annotated` dans le paramĂštre `q` { #add-query-to-annotated-in-the-q-parameter }
+
+Maintenant que nous avons cet `Annotated` dans lequel nous pouvons mettre plus dâinformations (dans ce cas une validation supplĂ©mentaire), ajoutez `Query` Ă lâintĂ©rieur de `Annotated`, et dĂ©finissez le paramĂštre `max_length` Ă `50` :
+
+{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
+
+Remarquez que la valeur par défaut est toujours `None`, donc le paramÚtre est toujours optionnel.
+
+Mais maintenant, avec `Query(max_length=50)` Ă lâintĂ©rieur de `Annotated`, nous indiquons Ă FastAPI que nous voulons **une validation supplĂ©mentaire** pour cette valeur, nous voulons quâelle ait au maximum 50 caractĂšres. đ
+
+/// tip | Astuce
+
+Ici nous utilisons `Query()` parce quâil sâagit dâun **paramĂštre de requĂȘte**. Plus tard nous verrons dâautres comme `Path()`, `Body()`, `Header()` et `Cookie()`, qui acceptent Ă©galement les mĂȘmes arguments que `Query()`.
///
-Ensuite, nous pouvons passer d'autres paramĂštres Ă `Query`. Dans cet exemple, le paramĂštre `max_length` qui s'applique aux chaĂźnes de caractĂšres :
+FastAPI va maintenant :
+
+- **Valider** les donnĂ©es en sâassurant que la longueur maximale est de 50 caractĂšres
+- Afficher une **erreur claire** au client quand les données ne sont pas valides
+- **Documenter** le paramĂštre dans la *chemin d'accĂšs* du schĂ©ma OpenAPI (il apparaĂźtra donc dans lâ**interface de documentation automatique**)
+
+## Alternative (ancienne) : `Query` comme valeur par défaut { #alternative-old-query-as-the-default-value }
+
+Les versions prĂ©cĂ©dentes de FastAPI (avant <abbr title="avant 2023-03">0.95.0</abbr>) exigeaient dâutiliser `Query` comme valeur par dĂ©faut de votre paramĂštre, au lieu de le mettre dans `Annotated`. Il y a de fortes chances que vous voyiez du code qui lâutilise encore, je vais donc vous lâexpliquer.
+
+/// tip | Astuce
+
+Pour du nouveau code et dĂšs que possible, utilisez `Annotated` comme expliquĂ© ci-dessus. Il y a de multiples avantages (expliquĂ©s ci-dessous) et aucun inconvĂ©nient. đ°
+
+///
+
+Voici comment vous utiliseriez `Query()` comme valeur par défaut du paramÚtre de votre fonction, en définissant le paramÚtre `max_length` à 50 :
+
+{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
+
+Comme, dans ce cas (sans utiliser `Annotated`), nous devons remplacer la valeur par dĂ©faut `None` dans la fonction par `Query()`, nous devons maintenant dĂ©finir la valeur par dĂ©faut avec le paramĂštre `Query(default=None)`, cela sert le mĂȘme objectif de dĂ©finir cette valeur par dĂ©faut (au moins pour FastAPI).
+
+Donc :
+
+```Python
+q: str | None = Query(default=None)
+```
+
+... rend le paramÚtre optionnel, avec une valeur par défaut de `None`, comme :
+
+```Python
+q: str | None = None
+```
+
+Mais la version avec `Query` le dĂ©clare explicitement comme Ă©tant un paramĂštre de requĂȘte.
+
+Ensuite, nous pouvons passer plus de paramĂštres Ă `Query`. Dans ce cas, le paramĂštre `max_length` qui sâapplique aux chaĂźnes de caractĂšres :
+
+```Python
+q: str | None = Query(default=None, max_length=50)
+```
+
+Cela validera les données, affichera une erreur claire lorsque les données ne sont pas valides et documentera le paramÚtre dans la *chemin d'accÚs* du schéma OpenAPI.
+
+### `Query` comme valeur par défaut ou dans `Annotated` { #query-as-the-default-value-or-in-annotated }
+
+Gardez Ă lâesprit quâen utilisant `Query` Ă lâintĂ©rieur de `Annotated`, vous ne pouvez pas utiliser le paramĂštre `default` de `Query`.
+
+Utilisez à la place la valeur par défaut réelle du paramÚtre de fonction. Sinon, ce serait incohérent.
+
+Par exemple, ceci nâest pas autorisĂ© :
+
+```Python
+q: Annotated[str, Query(default="rick")] = "morty"
+```
+
+... parce quâil nâest pas clair si la valeur par dĂ©faut doit ĂȘtre « rick » ou « morty ».
+
+Donc, vous utiliseriez (de préférence) :
```Python
-q: Union[str, None] = Query(default=None, max_length=50)
+q: Annotated[str, Query()] = "rick"
```
-Cela va valider les données, montrer une erreur claire si ces derniÚres ne sont pas valides, et documenter le paramÚtre dans le schéma `OpenAPI` de cette *path operation*.
+... ou dans des bases de code plus anciennes, vous trouverez :
+
+```Python
+q: str = Query(default="rick")
+```
+
+### Avantages de `Annotated` { #advantages-of-annotated }
+
+**Lâutilisation de `Annotated` est recommandĂ©e** plutĂŽt que la valeur par dĂ©faut dans les paramĂštres de fonction, câest **mieux** pour plusieurs raisons. đ€
+
+La valeur **par dĂ©faut** du **paramĂštre de fonction** est la **vraie valeur par dĂ©faut**, câest plus intuitif en Python en gĂ©nĂ©ral. đ
-## Rajouter plus de validation
+Vous pouvez **appeler** cette mĂȘme fonction dans **dâautres endroits** sans FastAPI, et elle **fonctionnera comme prĂ©vu**. Sâil y a un paramĂštre **requis** (sans valeur par dĂ©faut), votre **Ă©diteur** vous le signalera avec une erreur, **Python** se plaindra aussi si vous lâexĂ©cutez sans passer le paramĂštre requis.
-Vous pouvez aussi rajouter un second paramĂštre `min_length` :
+Quand vous nâutilisez pas `Annotated` et utilisez Ă la place lâ**ancienne** mĂ©thode avec la **valeur par dĂ©faut**, si vous appelez cette fonction sans FastAPI dans **dâautres endroits**, vous devez **penser** Ă passer les arguments Ă la fonction pour quâelle fonctionne correctement, sinon les valeurs seront diffĂ©rentes de ce que vous attendez (par ex. `QueryInfo` ou quelque chose de similaire au lieu dâune `str`). Et votre Ă©diteur ne se plaindra pas, et Python ne se plaindra pas en exĂ©cutant cette fonction, seulement quand les opĂ©rations internes Ă©choueront.
-{* ../../docs_src/query_params_str_validations/tutorial003.py hl[9] *}
+Comme `Annotated` peut avoir plus dâune annotation de mĂ©tadonnĂ©es, vous pouvez maintenant mĂȘme utiliser la mĂȘme fonction avec dâautres outils, comme <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. đ
-## Ajouter des validations par expressions réguliÚres
+## Ajouter plus de validations { #add-more-validations }
-On peut définir une <abbr title="Une expression réguliÚre, regex ou regexp est une suite de caractÚres qui définit un pattern de correspondance pour les chaßnes de caractÚres.">expression réguliÚre</abbr> à laquelle le paramÚtre doit correspondre :
+Vous pouvez également ajouter un paramÚtre `min_length` :
-{* ../../docs_src/query_params_str_validations/tutorial004.py hl[10] *}
+{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
-Cette expression réguliÚre vérifie que la valeur passée comme paramÚtre :
+## Ajouter des expressions réguliÚres { #add-regular-expressions }
-* `^` : commence avec les caractĂšres qui suivent, avec aucun caractĂšre avant ceux-lĂ .
-* `fixedquery` : a pour valeur exacte `fixedquery`.
-* `$` : se termine directement ensuite, n'a pas d'autres caractĂšres aprĂšs `fixedquery`.
+Vous pouvez dĂ©finir un `pattern` dâ<abbr title="Une expression rĂ©guliĂšre, regex ou regexp, est une suite de caractĂšres qui dĂ©finit un motif de recherche pour les chaĂźnes de caractĂšres.">expression rĂ©guliĂšre</abbr> auquel le paramĂštre doit correspondre :
-Si vous vous sentez perdu avec le concept d'**expression réguliÚre**, pas d'inquiétudes. Il s'agit d'une notion difficile pour beaucoup, et l'on peut déjà réussir à faire beaucoup sans jamais avoir à les manipuler.
+{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
-Mais si vous décidez d'apprendre à les utiliser, sachez qu'ensuite vous pouvez les utiliser directement dans **FastAPI**.
+Ce pattern dâexpression rĂ©guliĂšre spĂ©cifique vĂ©rifie que la valeur reçue pour le paramĂštre :
-## Valeurs par défaut
+- `^` : commence avec les caractĂšres qui suivent, nâa pas de caractĂšres avant.
+- `fixedquery` : a exactement la valeur `fixedquery`.
+- `$` : se termine lĂ , nâa pas dâautres caractĂšres aprĂšs `fixedquery`.
-De la mĂȘme façon que vous pouvez passer `None` comme premier argument pour l'utiliser comme valeur par dĂ©faut, vous pouvez passer d'autres valeurs.
+Si vous vous sentez perdu avec toutes ces idĂ©es dâ**« expression rĂ©guliĂšre »**, pas dâinquiĂ©tude. Câest un sujet difficile pour beaucoup. Vous pouvez dĂ©jĂ faire beaucoup de choses sans avoir besoin dâexpressions rĂ©guliĂšres.
-Disons que vous déclarez le paramÚtre `q` comme ayant une longueur minimale de `3`, et une valeur par défaut étant `"fixedquery"` :
+Désormais, vous savez que, lorsque vous en aurez besoin, vous pourrez les utiliser dans **FastAPI**.
-{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *}
+## Valeurs par défaut { #default-values }
-/// note | Rappel
+Vous pouvez, bien sûr, utiliser des valeurs par défaut autres que `None`.
-Avoir une valeur par défaut rend le paramÚtre optionnel.
+Disons que vous voulez dĂ©clarer le paramĂštre de requĂȘte `q` avec un `min_length` de `3`, et avec une valeur par dĂ©faut de « fixedquery » :
+
+{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
+
+/// note | Remarque
+
+Avoir une valeur par dĂ©faut de nâimporte quel type, y compris `None`, rend le paramĂštre optionnel (non requis).
///
-## Rendre ce paramĂštre requis
+## ParamĂštres requis { #required-parameters }
-Quand on ne déclare ni validation, ni métadonnée, on peut rendre le paramÚtre `q` requis en ne lui déclarant juste aucune valeur par défaut :
+Quand nous nâavons pas besoin de dĂ©clarer plus de validations ou de mĂ©tadonnĂ©es, nous pouvons rendre le paramĂštre de requĂȘte `q` requis en nâindiquant simplement pas de valeur par dĂ©faut, comme :
```Python
q: str
```
-Ă la place de :
+au lieu de :
```Python
-q: Union[str, None] = None
+q: str | None = None
```
-Mais maintenant, on déclare `q` avec `Query`, comme ceci :
+Mais maintenant nous le déclarons avec `Query`, par exemple ainsi :
```Python
-q: Union[str, None] = Query(default=None, min_length=3)
+q: Annotated[str | None, Query(min_length=3)] = None
```
-Donc pour déclarer une valeur comme requise tout en utilisant `Query`, il faut utiliser `...` comme premier argument :
+Donc, lorsque vous avez besoin de déclarer une valeur comme requise tout en utilisant `Query`, vous pouvez simplement ne pas déclarer de valeur par défaut :
-{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
+{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
-/// info
+### Requis, peut valoir `None` { #required-can-be-none }
-Si vous n'avez jamais vu ce `...` auparavant : c'est une des constantes natives de Python <a href="https://docs.python.org/fr/3/library/constants.html#Ellipsis" class="external-link" target="_blank">appelée "Ellipsis"</a>.
+Vous pouvez dĂ©clarer quâun paramĂštre accepte `None`, mais quâil est tout de mĂȘme requis. Cela obligerait les clients Ă envoyer une valeur, mĂȘme si la valeur est `None`.
-///
+Pour ce faire, vous pouvez déclarer que `None` est un type valide tout en ne déclarant pas de valeur par défaut :
-Cela indiquera à **FastAPI** que la présence de ce paramÚtre est obligatoire.
+{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
-## Liste de paramĂštres / valeurs multiples via Query
+## Liste de paramĂštres de requĂȘte / valeurs multiples { #query-parameter-list-multiple-values }
-Quand on dĂ©finit un paramĂštre de requĂȘte explicitement avec `Query` on peut aussi dĂ©clarer qu'il reçoit une liste de valeur, ou des "valeurs multiples".
+Quand vous dĂ©finissez un paramĂštre de requĂȘte explicitement avec `Query`, vous pouvez aussi dĂ©clarer quâil reçoit une liste de valeurs, autrement dit, quâil reçoit des valeurs multiples.
-Par exemple, pour dĂ©clarer un paramĂštre de requĂȘte `q` qui peut apparaĂźtre plusieurs fois dans une URL, on Ă©crit :
+Par exemple, pour dĂ©clarer un paramĂštre de requĂȘte `q` qui peut apparaĂźtre plusieurs fois dans lâURL, vous pouvez Ă©crire :
-{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
-Ce qui fait qu'avec une URL comme :
+Ensuite, avec une URL comme :
```
http://localhost:8000/items/?q=foo&q=bar
```
-vous recevriez les valeurs des multiples paramĂštres de requĂȘte `q` (`foo` et `bar`) dans une `list` Python au sein de votre fonction de **path operation**, dans le paramĂštre de fonction `q`.
+vous recevriez les valeurs des multiples paramĂštres de requĂȘte `q` (`foo` et `bar`) dans une `list` Python Ă lâintĂ©rieur de votre fonction de *chemin d'accĂšs*, dans le *paramĂštre de fonction* `q`.
-Donc la réponse de cette URL serait :
+Donc, la réponse pour cette URL serait :
```JSON
{
/// tip | Astuce
-Pour dĂ©clarer un paramĂštre de requĂȘte de type `list`, comme dans l'exemple ci-dessus, il faut explicitement utiliser `Query`, sinon cela sera interprĂ©tĂ© comme faisant partie du corps de la requĂȘte.
+Pour dĂ©clarer un paramĂštre de requĂȘte avec un type `list`, comme dans lâexemple ci-dessus, vous devez explicitement utiliser `Query`, sinon il serait interprĂ©tĂ© comme faisant partie du corps de la requĂȘte.
///
-La documentation sera donc mise Ă jour automatiquement pour autoriser plusieurs valeurs :
+Lâinterface de documentation interactive de lâAPI sera mise Ă jour en consĂ©quence, pour autoriser plusieurs valeurs :
<img src="/img/tutorial/query-params-str-validations/image02.png">
-### Combiner liste de paramÚtres et valeurs par défaut
+### Liste de paramĂštres de requĂȘte / valeurs multiples avec valeurs par dĂ©faut { #query-parameter-list-multiple-values-with-defaults }
-Et l'on peut aussi définir une liste de valeurs par défaut si aucune n'est fournie :
+Vous pouvez Ă©galement dĂ©finir une `list` de valeurs par dĂ©faut si aucune nâest fournie :
-{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
Si vous allez Ă :
http://localhost:8000/items/
```
-la valeur par défaut de `q` sera : `["foo", "bar"]`
-
-et la réponse sera :
+la valeur par défaut de `q` sera : `["foo", "bar"]` et votre réponse sera :
```JSON
{
}
```
-#### Utiliser `list`
+#### Utiliser simplement `list` { #using-just-list }
-Il est aussi possible d'utiliser directement `list` plutĂŽt que `List[str]` :
+Vous pouvez aussi utiliser `list` directement au lieu de `list[str]` :
-{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *}
+{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
-/// note
+/// note | Remarque
-Dans ce cas-là , **FastAPI** ne vérifiera pas le contenu de la liste.
+Gardez Ă lâesprit que dans ce cas, FastAPI ne vĂ©rifiera pas le contenu de la liste.
-Par exemple, `List[int]` vérifiera (et documentera) que la liste est bien entiÚrement composée d'entiers. Alors qu'un simple `list` ne ferait pas cette vérification.
+Par exemple, `list[int]` vĂ©rifierait (et documenterait) que le contenu de la liste est composĂ© dâentiers. Mais un simple `list` ne le ferait pas.
///
-## Déclarer des métadonnées supplémentaires
+## Déclarer plus de métadonnées { #declare-more-metadata }
-On peut aussi ajouter plus d'informations sur le paramĂštre.
+Vous pouvez ajouter plus dâinformations Ă propos du paramĂštre.
-Ces informations seront incluses dans le schéma `OpenAPI` généré et utilisées par la documentation interactive ou les outils externes utilisés.
+Ces informations seront incluses dans lâOpenAPI gĂ©nĂ©rĂ© et utilisĂ©es par les interfaces de documentation et les outils externes.
-/// note
+/// note | Remarque
-Gardez en tĂȘte que les outils externes utilisĂ©s ne supportent pas forcĂ©ment tous parfaitement OpenAPI.
+Gardez Ă lâesprit que diffĂ©rents outils peuvent avoir des niveaux de prise en charge dâOpenAPI diffĂ©rents.
-Il se peut donc que certains d'entre eux n'utilisent pas toutes les mĂ©tadonnĂ©es que vous avez dĂ©clarĂ©es pour le moment, bien que dans la plupart des cas, les fonctionnalitĂ©s manquantes ont prĂ©vu d'ĂȘtre implĂ©mentĂ©es.
+Certains dâentre eux pourraient ne pas encore afficher toutes les informations supplĂ©mentaires dĂ©clarĂ©es, bien que, dans la plupart des cas, la fonctionnalitĂ© manquante soit dĂ©jĂ prĂ©vue au dĂ©veloppement.
///
Vous pouvez ajouter un `title` :
-{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *}
+{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
Et une `description` :
-{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *}
+{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
-## Alias de paramĂštres
+## ParamĂštres avec alias { #alias-parameters }
-Imaginez que vous vouliez que votre paramĂštre se nomme `item-query`.
+Imaginez que vous vouliez que le paramĂštre soit `item-query`.
-Comme dans la requĂȘte :
+Comme dans :
```
http://127.0.0.1:8000/items/?item-query=foobaritems
```
-Mais `item-query` n'est pas un nom de variable valide en Python.
+Mais `item-query` nâest pas un nom de variable Python valide.
-Le nom le plus proche serait `item_query`.
+Le plus proche serait `item_query`.
-Mais vous avez vraiment envie que ce soit exactement `item-query`...
+Mais vous avez quand mĂȘme besoin que ce soit exactement `item-query` ...
-Pour cela vous pouvez déclarer un `alias`, et cet alias est ce qui sera utilisé pour trouver la valeur du paramÚtre :
+Vous pouvez alors déclarer un `alias`, et cet alias sera utilisé pour trouver la valeur du paramÚtre :
-{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *}
+{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
-## Déprécier des paramÚtres
+## Déprécier des paramÚtres { #deprecating-parameters }
-Disons que vous ne vouliez plus utiliser ce paramÚtre désormais.
+Disons que vous nâaimez plus ce paramĂštre.
-Il faut qu'il continue à exister pendant un certain temps car vos clients l'utilisent, mais vous voulez que la documentation mentionne clairement que ce paramÚtre est <abbr title="obsolÚte, recommandé de ne pas l'utiliser">déprécié</abbr>.
+Vous devez le laisser lĂ quelque temps car des clients lâutilisent, mais vous voulez que les documents lâaffichent clairement comme <abbr title="obsolĂšte, recommandĂ© de ne pas lâutiliser">dĂ©prĂ©ciĂ©</abbr>.
-On utilise alors l'argument `deprecated=True` de `Query` :
+Passez alors le paramĂštre `deprecated=True` Ă `Query` :
-{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *}
+{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
-La documentation le présentera comme il suit :
+Les documents lâafficheront ainsi :
<img src="/img/tutorial/query-params-str-validations/image01.png">
-## Pour résumer
+## Exclure des paramĂštres dâOpenAPI { #exclude-parameters-from-openapi }
+
+Pour exclure un paramĂštre de requĂȘte du schĂ©ma OpenAPI gĂ©nĂ©rĂ© (et donc, des systĂšmes de documentation automatiques), dĂ©finissez le paramĂštre `include_in_schema` de `Query` Ă `False` :
+
+{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
+
+## Validation personnalisée { #custom-validation }
+
+Il peut y avoir des cas oĂč vous devez faire une **validation personnalisĂ©e** qui ne peut pas ĂȘtre rĂ©alisĂ©e avec les paramĂštres montrĂ©s ci-dessus.
+
+Dans ces cas, vous pouvez utiliser une **fonction de validation personnalisée** qui est appliquée aprÚs la validation normale (par ex. aprÚs avoir validé que la valeur est une `str`).
+
+Vous pouvez y parvenir en utilisant <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">`AfterValidator` de Pydantic</a> Ă lâintĂ©rieur de `Annotated`.
+
+/// tip | Astuce
+
+Pydantic a aussi <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> et dâautres. đ€
+
+///
+
+Par exemple, ce validateur personnalisĂ© vĂ©rifie que lâID dâitem commence par `isbn-` pour un numĂ©ro de livre <abbr title="International Standard Book Number - NumĂ©ro international normalisĂ© du livre">ISBN</abbr> ou par `imdb-` pour un ID dâURL de film <abbr title="IMDB (Internet Movie Database) est un site web contenant des informations sur les films">IMDB</abbr> :
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
+
+/// info
+
+Câest disponible avec Pydantic version 2 ou supĂ©rieure. đ
+
+///
+
+/// tip | Astuce
+
+Si vous devez faire un type de validation qui nécessite de communiquer avec un **composant externe**, comme une base de données ou une autre API, vous devez plutÎt utiliser les **Dépendances de FastAPI**, vous en apprendrez davantage plus tard.
+
+Ces validateurs personnalisĂ©s sont destinĂ©s aux Ă©lĂ©ments qui peuvent ĂȘtre vĂ©rifiĂ©s **uniquement** avec les **mĂȘmes donnĂ©es** fournies dans la requĂȘte.
+
+///
+
+### Comprendre ce code { #understand-that-code }
+
+Le point important est simplement dâutiliser **`AfterValidator` avec une fonction Ă lâintĂ©rieur de `Annotated`**. NâhĂ©sitez pas Ă passer cette partie. đ€ž
+
+---
+
+Mais si vous ĂȘtes curieux de cet exemple de code spĂ©cifique et que vous ĂȘtes toujours partant, voici quelques dĂ©tails supplĂ©mentaires.
+
+#### ChaĂźne avec `value.startswith()` { #string-with-value-startswith }
+
+Avez-vous remarqué ? Une chaßne utilisant `value.startswith()` peut prendre un tuple, et elle vérifiera chaque valeur du tuple :
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
+
+#### Un élément aléatoire { #a-random-item }
+
+Avec `data.items()` nous obtenons un <abbr title="Quelque chose que lâon peut itĂ©rer avec une boucle for, comme une liste, un set, etc.">objet itĂ©rable</abbr> avec des tuples contenant la clĂ© et la valeur pour chaque Ă©lĂ©ment du dictionnaire.
+
+Nous convertissons cet objet itérable en une `list` propre avec `list(data.items())`.
+
+Ensuite, avec `random.choice()` nous pouvons obtenir une **valeur aléatoire** depuis la liste, nous obtenons donc un tuple `(id, name)`. Ce sera quelque chose comme `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
+
+Puis nous **affectons ces deux valeurs** du tuple aux variables `id` et `name`.
+
+Ainsi, si lâutilisateur nâa pas fourni dâID dâitem, il recevra quand mĂȘme une suggestion alĂ©atoire.
+
+... nous faisons tout cela en **une seule ligne simple**. đ€Ż Vous nâadorez pas Python ? đ
+
+{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
+
+## Récapitulatif { #recap }
+
+Vous pouvez déclarer des validations et des métadonnées supplémentaires pour vos paramÚtres.
-Il est possible d'ajouter des validateurs et métadonnées pour vos paramÚtres.
+Validations et métadonnées génériques :
-Validateurs et métadonnées génériques:
+- `alias`
+- `title`
+- `description`
+- `deprecated`
-* `alias`
-* `title`
-* `description`
-* `deprecated`
+Validations spécifiques aux chaßnes :
-Validateurs spécifiques aux chaßnes de caractÚres :
+- `min_length`
+- `max_length`
+- `pattern`
-* `min_length`
-* `max_length`
-* `regex`
+Validations personnalisées avec `AfterValidator`.
-Parmi ces exemples, vous avez pu voir comment déclarer des validateurs pour les chaßnes de caractÚres.
+Dans ces exemples, vous avez vu comment déclarer des validations pour des valeurs `str`.
-Dans les prochains chapitres, vous verrez comment déclarer des validateurs pour d'autres types, comme les nombres.
+Voyez les prochains chapitres pour apprendre Ă dĂ©clarer des validations pour dâautres types, comme les nombres.
-# ParamĂštres de requĂȘte
+# ParamĂštres de requĂȘte { #query-parameters }
-Quand vous dĂ©clarez des paramĂštres dans votre fonction de chemin qui ne font pas partie des paramĂštres indiquĂ©s dans le chemin associĂ©, ces paramĂštres sont automatiquement considĂ©rĂ©s comme des paramĂštres de "requĂȘte".
+Quand vous déclarez d'autres paramÚtres de fonction qui ne font pas partie des paramÚtres de chemin, ils sont automatiquement interprétés comme des paramÚtres de « query ».
-{* ../../docs_src/query_params/tutorial001.py hl[9] *}
+{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
-La partie appelĂ©e requĂȘte (ou **query**) dans une URL est l'ensemble des paires clĂ©s-valeurs placĂ©es aprĂšs le `?` , sĂ©parĂ©es par des `&`.
+La query est l'ensemble des paires clé-valeur placées aprÚs le `?` dans une URL, séparées par des caractÚres `&`.
Par exemple, dans l'URL :
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-...les paramĂštres de requĂȘte sont :
+... les paramĂštres de requĂȘte sont :
-* `skip` : avec une valeur de`0`
+* `skip` : avec une valeur de `0`
* `limit` : avec une valeur de `10`
-Faisant partie de l'URL, ces valeurs sont des chaĂźnes de caractĂšres (`str`).
+Comme ils font partie de l'URL, ce sont « naturellement » des chaßnes de caractÚres.
-Mais quand on les déclare avec des types Python (dans l'exemple précédent, en tant qu'`int`), elles sont converties dans les types renseignés.
+Mais lorsque vous les déclarez avec des types Python (dans l'exemple ci-dessus, en tant que `int`), ils sont convertis vers ce type et validés par rapport à celui-ci.
-Toutes les fonctionnalitĂ©s qui s'appliquent aux paramĂštres de chemin s'appliquent aussi aux paramĂštres de requĂȘte :
+Tous les mĂȘmes processus qui s'appliquaient aux paramĂštres de chemin s'appliquent aussi aux paramĂštres de requĂȘte :
-* Support de l'éditeur : vérification d'erreurs, auto-complétion, etc.
-* <abbr title="conversion de la chaĂźne de caractĂšres venant de la requĂȘte HTTP en donnĂ©es Python">"Parsing"</abbr> de donnĂ©es.
-* Validation de données.
-* Annotations d'API et documentation automatique.
+* Prise en charge de l'éditeur (évidemment)
+* <abbr title="conversion de la chaĂźne provenant d'une requĂȘte HTTP en donnĂ©es Python">« parsing »</abbr> des donnĂ©es
+* Validation des données
+* Documentation automatique
-## Valeurs par défaut
+## Valeurs par défaut { #defaults }
-Les paramĂštres de requĂȘte ne sont pas une partie fixe d'un chemin, ils peuvent ĂȘtre optionnels et avoir des valeurs par dĂ©faut.
+Comme les paramĂštres de requĂȘte ne sont pas une partie fixe d'un chemin, ils peuvent ĂȘtre optionnels et avoir des valeurs par dĂ©faut.
-Dans l'exemple ci-dessus, ils ont des valeurs par défaut qui sont `skip=0` et `limit=10`.
+Dans l'exemple ci-dessus, ils ont des valeurs par défaut `skip=0` et `limit=10`.
Donc, accéder à l'URL :
http://127.0.0.1:8000/items/
```
-serait équivalent à accéder à l'URL :
+serait équivalent à accéder à :
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-Mais si vous accédez à , par exemple :
+Mais si vous accédez, par exemple, à :
```
http://127.0.0.1:8000/items/?skip=20
```
-Les valeurs des paramĂštres de votre fonction seront :
+Les valeurs des paramĂštres dans votre fonction seront :
-* `skip=20` : car c'est la valeur déclarée dans l'URL.
-* `limit=10` : car `limit` n'a pas été déclaré dans l'URL, et que la valeur par défaut était `10`.
+* `skip=20` : car vous l'avez défini dans l'URL
+* `limit=10` : car c'était la valeur par défaut
-## ParamĂštres optionnels
+## ParamĂštres optionnels { #optional-parameters }
-De la mĂȘme façon, vous pouvez dĂ©finir des paramĂštres de requĂȘte comme optionnels, en leur donnant comme valeur par dĂ©faut `None` :
+De la mĂȘme façon, vous pouvez dĂ©clarer des paramĂštres de requĂȘte optionnels, en dĂ©finissant leur valeur par dĂ©faut Ă `None` :
-{* ../../docs_src/query_params/tutorial002.py hl[9] *}
+{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
-Ici, le paramÚtre `q` sera optionnel, et aura `None` comme valeur par défaut.
+Dans ce cas, le paramÚtre de fonction `q` sera optionnel et vaudra `None` par défaut.
-/// check | Remarque
+/// check | Vérifications
-On peut voir que **FastAPI** est capable de dĂ©tecter que le paramĂštre de chemin `item_id` est un paramĂštre de chemin et que `q` n'en est pas un, c'est donc un paramĂštre de requĂȘte.
+Notez Ă©galement que FastAPI est suffisamment intelligent pour remarquer que le paramĂštre de chemin `item_id` est un paramĂštre de chemin et que `q` ne l'est pas, c'est donc un paramĂštre de requĂȘte.
///
-/// note
+## Conversion des types des paramĂštres de requĂȘte { #query-parameter-type-conversion }
-**FastAPI** saura que `q` est optionnel grĂące au `=None`.
+Vous pouvez aussi déclarer des types `bool`, ils seront convertis :
-Le `Optional` dans `Optional[str]` n'est pas utilisĂ© par **FastAPI** (**FastAPI** n'en utilisera que la partie `str`), mais il servira tout de mĂȘme Ă votre Ă©diteur de texte pour dĂ©tecter des erreurs dans votre code.
+{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
-///
-
-## Conversion des types des paramĂštres de requĂȘte
-
-Vous pouvez aussi dĂ©clarer des paramĂštres de requĂȘte comme boolĂ©ens (`bool`), **FastAPI** les convertira :
-
-{* ../../docs_src/query_params/tutorial003.py hl[9] *}
-
-Avec ce code, en allant sur :
+Dans ce cas, si vous allez sur :
```
http://127.0.0.1:8000/items/foo?short=1
http://127.0.0.1:8000/items/foo?short=yes
```
-ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la premiÚre lettre en majuscule, etc.), votre fonction considérera le paramÚtre `short` comme ayant une valeur booléenne à `True`. Sinon la valeur sera à `False`.
+ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la premiĂšre lettre en majuscule, etc.), votre fonction verra le paramĂštre `short` avec une valeur `bool` Ă `True`. Sinon la valeur sera Ă `False`.
-## Multiples paramĂštres de chemin et de requĂȘte
+## Multiples paramĂštres de chemin et de requĂȘte { #multiple-path-and-query-parameters }
-Vous pouvez dĂ©clarer plusieurs paramĂštres de chemin et paramĂštres de requĂȘte dans la mĂȘme fonction, **FastAPI** saura comment les gĂ©rer.
+Vous pouvez dĂ©clarer plusieurs paramĂštres de chemin et paramĂštres de requĂȘte en mĂȘme temps, FastAPI sait lequel est lequel.
Et vous n'avez pas besoin de les déclarer dans un ordre spécifique.
-Ils seront détectés par leurs noms :
+Ils seront détectés par leur nom :
-{* ../../docs_src/query_params/tutorial004.py hl[8,10] *}
+{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
-## ParamĂštres de requĂȘte requis
+## ParamĂštres de requĂȘte requis { #required-query-parameters }
-Quand vous dĂ©clarez une valeur par dĂ©faut pour un paramĂštre qui n'est pas un paramĂštre de chemin (actuellement, nous n'avons vu que les paramĂštres de requĂȘte), alors ce paramĂštre n'est pas requis.
+Quand vous dĂ©clarez une valeur par dĂ©faut pour des paramĂštres qui ne sont pas des paramĂštres de chemin (pour l'instant, nous n'avons vu que les paramĂštres de requĂȘte), alors ils ne sont pas requis.
-Si vous ne voulez pas leur donner de valeur par défaut mais juste les rendre optionnels, utilisez `None` comme valeur par défaut.
+Si vous ne voulez pas leur donner de valeur spécifique mais simplement les rendre optionnels, définissez la valeur par défaut à `None`.
-Mais si vous voulez rendre un paramĂštre de requĂȘte obligatoire, vous pouvez juste ne pas y affecter de valeur par dĂ©faut :
+Mais si vous voulez rendre un paramĂštre de requĂȘte obligatoire, vous pouvez simplement ne dĂ©clarer aucune valeur par dĂ©faut :
-{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
+{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
-Ici le paramĂštre `needy` est un paramĂštre requis (ou obligatoire) de type `str`.
+Ici, le paramĂštre de requĂȘte `needy` est un paramĂštre de requĂȘte requis de type `str`.
-Si vous ouvrez une URL comme :
+Si vous ouvrez dans votre navigateur une URL comme :
```
http://127.0.0.1:8000/items/foo-item
```
-...sans ajouter le paramĂštre requis `needy`, vous aurez une erreur :
+... sans ajouter le paramĂštre requis `needy`, vous verrez une erreur comme :
```JSON
{
- "detail": [
- {
- "loc": [
- "query",
- "needy"
- ],
- "msg": "field required",
- "type": "value_error.missing"
- }
- ]
+ "detail": [
+ {
+ "type": "missing",
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "Field required",
+ "input": null
+ }
+ ]
}
```
-La présence de `needy` étant nécessaire, vous auriez besoin de l'insérer dans l'URL :
+Comme `needy` est un paramÚtre requis, vous devez le définir dans l'URL :
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
-...ce qui fonctionnerait :
+... cela fonctionnerait :
```JSON
{
}
```
-Et bien sur, vous pouvez définir certains paramÚtres comme requis, certains avec des valeurs par défaut et certains entiÚrement optionnels :
+Et bien sûr, vous pouvez définir certains paramÚtres comme requis, certains avec une valeur par défaut et certains entiÚrement optionnels :
-{* ../../docs_src/query_params/tutorial006.py hl[10] *}
+{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
-Ici, on a donc 3 paramĂštres de requĂȘte :
+Dans ce cas, il y a 3 paramĂštres de requĂȘte :
-* `needy`, requis et de type `str`.
-* `skip`, un `int` avec comme valeur par défaut `0`.
+* `needy`, un `str` requis.
+* `skip`, un `int` avec une valeur par défaut de `0`.
* `limit`, un `int` optionnel.
/// tip | Astuce
-Vous pouvez utiliser les `Enum`s de la mĂȘme façon qu'avec les [ParamĂštres de chemin](path-params.md#valeurs-predefinies){.internal-link target=_blank}.
+Vous pourriez aussi utiliser des `Enum`s de la mĂȘme façon qu'avec les [ParamĂštres de chemin](path-params.md#predefined-values){.internal-link target=_blank}.
///