@ -36,6 +36,6 @@ Pour plus de commodités, **FastAPI** fournit les objets `starlette.responses` s
## Documents OpenAPI et API { #openapi-and-api-docs }
## 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.
Si vous renvoyez directement des codes HTTP et des réponses supplémentaires, ils ne seront pas inclus dans le schéma OpenAPI (les documents 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](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}.
@ -40,7 +40,7 @@ Même si elles se trouvent dans des modules différents (fichiers Python).
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` :
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` :
## Description avancée depuis la docstring { #advanced-description-from-docstring }
## Description avancée depuis la docstring { #advanced-description-from-docstring }
@ -92,7 +92,7 @@ Vous pouvez étendre le schéma OpenAPI pour un chemin d’accès en utilisant l
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) :
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) :
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 <abbrtitle="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.
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 <dfntitle="converti d'un format simple, comme des octets, en objets Python">parsé</dfn> 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.
Néanmoins, nous pouvons déclarer le schéma attendu pour le corps de la requête.
@ -153,7 +153,7 @@ Et vous pourriez le faire même si le type de données dans la requête n’est
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 :
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 :
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.
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.
@ -161,7 +161,7 @@ Ensuite, nous utilisons directement la requête et extrayons le corps en tant qu
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 :
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 :
@ -22,7 +22,7 @@ En fait, vous pouvez retourner n'importe quelle `Response` ou n'importe quelle s
Et quand vous retournez une `Response`, **FastAPI** la transmet directement.
Et quand vous retournez une `Response`, **FastAPI** la transmet directement.
Elle ne fera aucune conversion de données avec les modèles Pydantic, elle ne convertira pas le contenu en un type quelconque.
Elle ne fera aucune conversion de données avec les modèles Pydantic, elle ne convertira pas le contenu en un type quelconque, etc.
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.
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.
@ -54,7 +54,7 @@ Disons que vous voulez retourner une réponse <a href="https://en.wikipedia.org/
Vous pouvez mettre votre contenu XML dans une chaîne de caractères, la placer dans une `Response`, et la retourner :
Vous pouvez mettre votre contenu XML dans une chaîne de caractères, la placer dans une `Response`, et la retourner :
C'est le framework Python le plus populaire et il bénéficie d'une grande confiance. Il est utilisé pour construire
C'est le framework Python le plus populaire et il bénéficie d'une grande confiance. Il est utilisé pour construire
des systèmes tel qu'Instagram.
des systèmes tel qu'Instagram.
@ -26,18 +26,18 @@ Il est relativement fortement couplé aux bases de données relationnelles (comm
n'est pas très facile d'utiliser une base de données NoSQL (comme Couchbase, MongoDB, Cassandra, etc.) comme principal moyen de
n'est pas très facile d'utiliser une base de données NoSQL (comme Couchbase, MongoDB, Cassandra, etc.) comme principal moyen de
stockage.
stockage.
Il a été créé pour générer le HTML en backend, pas pour créer des API consommées par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systèmes (comme les appareils <abbrtitle="Internet of Things">IoT</abbr>) communiquant avec lui.
Il a été créé pour générer le HTML en backend, pas pour créer des API consommées par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systèmes (comme les appareils <abbrtitle="Internet of Things - Internet des objets">IoT</abbr>) communiquant avec lui.
Django REST framework a été conçu comme une boîte à outils flexible permettant de construire des API Web à partir de Django, afin d'améliorer ses capacités en matière d'API.
Django REST framework a été conçu comme une boîte à outils flexible permettant de construire des API Web à partir de Django, afin d'améliorer ses capacités en matière d'API.
Il est utilisé par de nombreuses entreprises, dont Mozilla, Red Hat et Eventbrite.
Il est utilisé par de nombreuses entreprises, dont Mozilla, Red Hat et Eventbrite.
Il s'agissait de l'un des premiers exemples de **documentation automatique pour API**, et c'est précisément l'une des
Il s'agissait de l'un des premiers exemples de **documentation automatique pour API**, et c'est précisément l'une des
premières idées qui a inspiré "la recherche de"**FastAPI**.
premières idées qui a inspiré « la recherche de »**FastAPI**.
/// note
/// note | Remarque
Django REST framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé.
Django REST framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé.
@ -49,9 +49,9 @@ Avoir une interface de documentation automatique de l'API.
Flask est un "micro-framework", il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django.
Flask est un « micro‑framework », il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django.
Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données.
Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données.
@ -60,20 +60,20 @@ technique par moments.
Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins.
Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins.
Ce découplage des parties, et le fait d'être un "micro-framework" qui puisse être étendu pour couvrir exactement ce
Ce découplage des parties, et le fait d'être un « micro‑framework » qui puisse être étendu pour couvrir exactement ce
qui est nécessaire, était une caractéristique clé que je voulais conserver.
qui est nécessaire, était une caractéristique clé que je voulais conserver.
Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un "Django REST Framework" pour Flask.
Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un « Django REST Framework » pour Flask.
/// check | A inspiré **FastAPI** à
/// check | A inspiré **FastAPI** à
Être un micro-framework. Il est donc facile de combiner les outils et les pièces nécessaires.
Être un micro‑framework. Il est donc facile de combiner les outils et les pièces nécessaires.
Proposer un système de routage simple et facile à utiliser.
Proposer un système de routage simple et facile à utiliser.
En contrepartie l'API _des opérations de chemin_ de FastAPI pourrait ressembler à ceci :
L’opération de chemin d'accès correspondante dans **FastAPI** pourrait ressembler à ceci :
```Python hl_lines="1"
```Python hl_lines="1"
@app.get("/some/url")
@app.get("/some/url")
@ -109,13 +109,13 @@ Notez les similitudes entre `requests.get(...)` et `@app.get(...)`.
/// check | A inspiré **FastAPI** à
/// check | A inspiré **FastAPI** à
Avoir une API simple et intuitive.
* Avoir une API simple et intuitive.
* Utiliser les noms de méthodes HTTP (opérations) directement, de manière simple et intuitive.
Utiliser les noms de méthodes HTTP (opérations) directement, de manière simple et intuitive. \* Avoir des valeurs par défaut raisonnables, mais des personnalisations puissantes.
* Avoir des valeurs par défaut raisonnables, mais des personnalisations puissantes.
L'une des principales fonctionnalités nécessaires aux systèmes API est la "<abbrtitle="égalementappelée
L'une des principales fonctionnalités nécessaires aux systèmes API est la « <dfntitle="aussi appelé : marshalling, conversion">sérialisation</dfn> » des données, qui consiste à prendre les données du code (Python) et à
marshalling, conversion">sérialisation</abbr>" des données, qui consiste à prendre les données du code (Python) et à
les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des
les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des
données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc.
données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc.
@ -163,19 +162,17 @@ Sans un système de validation des données, vous devriez effectuer toutes les v
Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée.
Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée.
Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque <abbrtitle="ladéfinitionde
Mais elle a été créée avant que les annotations de type n'existent en Python. Ainsi, pour définir chaque <dfntitle="la définition de la façon dont les données doivent être formées">schéma</dfn>, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow.
la façon dont les données doivent être formées">schéma</abbr>, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow.
/// check | A inspiré **FastAPI** à
/// check | A inspiré **FastAPI** à
Utilisez du code pour définir des "schémas" qui fournissent automatiquement les types de données et la validation.
Utilisez du code pour définir des « schémas » qui fournissent automatiquement les types de données et la validation.
Une autre grande fonctionnalité requise par les API est le <abbrtitle="lalectureetlaconversionendonnées
Une autre grande fonctionnalité requise par les API est l’<dfntitle="lecture et conversion en données Python">analyse</dfn> des données provenant des requêtes entrantes.
Python">parsing</abbr> des données provenant des requêtes entrantes.
Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask.
Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask.
@ -195,7 +192,7 @@ Disposer d'une validation automatique des données des requêtes entrantes.
Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=\_blank}.
Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=_blank}.
/// info
/// info
@ -258,15 +255,15 @@ Générer le schéma OpenAPI automatiquement, à partir du même code qui défin
///
///
### <ahref="https://nestjs.com/"class="external-link"target="_blank">NestJS</a> (et <ahref="https://angular.io/"class="external-link"target="_blank">Angular</a>)
### <ahref="https://nestjs.com/"class="external-link"target="_blank">NestJS</a> (et <ahref="https://angular.io/"class="external-link"target="_blank">Angular</a>) { #nestjs-and-angular }
Ce n'est même pas du Python, NestJS est un framework JavaScript (TypeScript) NodeJS inspiré d'Angular.
Ce n'est même pas du Python, NestJS est un framework JavaScript (TypeScript) NodeJS inspiré d'Angular.
Il réalise quelque chose de similaire à ce qui peut être fait avec Flask-apispec.
Il réalise quelque chose de similaire à ce qui peut être fait avec Flask-apispec.
Il possède un système d'injection de dépendances intégré, inspiré d'Angular 2. Il nécessite de pré-enregistrer les "injectables" (comme tous les autres systèmes d'injection de dépendances que je connais), donc, cela ajoute à la verbosité et à la répétition du code.
Il possède un système d'injection de dépendances intégré, inspiré d'Angular 2. Il nécessite de pré-enregistrer les « injectables » (comme tous les autres systèmes d'injection de dépendances que je connais), donc, cela ajoute à la verbosité et à la répétition du code.
Comme les paramètres sont décrits avec des types TypeScript (similaires aux type hints de Python), la prise en charge
Comme les paramètres sont décrits avec des types TypeScript (similaires aux annotations de type de Python), la prise en charge
par l'éditeur est assez bonne.
par l'éditeur est assez bonne.
Mais comme les données TypeScript ne sont pas préservées après la compilation en JavaScript, il ne peut pas compter sur les types pour définir la validation, la sérialisation et la documentation en même temps. En raison de cela et de certaines décisions de conception, pour obtenir la validation, la sérialisation et la génération automatique de schémas, il est nécessaire d'ajouter des décorateurs à de nombreux endroits. Cela devient donc assez verbeux.
Mais comme les données TypeScript ne sont pas préservées après la compilation en JavaScript, il ne peut pas compter sur les types pour définir la validation, la sérialisation et la documentation en même temps. En raison de cela et de certaines décisions de conception, pour obtenir la validation, la sérialisation et la génération automatique de schémas, il est nécessaire d'ajouter des décorateurs à de nombreux endroits. Cela devient donc assez verbeux.
@ -281,7 +278,7 @@ Disposer d'un puissant système d'injection de dépendances. Trouver un moyen de
Falcon est un autre framework Python haute performance, il est conçu pour être minimal, et est utilisé comme fondation pour d'autres frameworks comme Hug.
Falcon est un autre framework Python haute performance, il est conçu pour être minimal, et est utilisé comme fondation pour d'autres frameworks comme Hug.
Il utilise le standard précédent pour les frameworks web Python (WSGI) qui est synchrone, donc il ne peut pas gérer les WebSockets et d'autres cas d'utilisation. Néanmoins, il offre de très bonnes performances.
Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une « requête » et une « réponse ». Ensuite, vous
« lisez » des parties de la requête et « écrivez » des parties dans la réponse. En raison de cette conception, il n'est
Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une "requête" et une "réponse". Ensuite, vous
"lisez" des parties de la requête et "écrivez" des parties dans la réponse. En raison de cette conception, il n'est
pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction.
pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction.
Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres.
Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres.
@ -323,20 +318,20 @@ Bien que dans FastAPI, il est facultatif, et est utilisé principalement pour d
J'ai découvert Molten lors des premières étapes de développement de **FastAPI**. Et il a des idées assez similaires :
J'ai découvert Molten lors des premières étapes de développement de **FastAPI**. Et il a des idées assez similaires :
- Basé sur les type hints Python.
* Basé sur les annotations de type Python.
- Validation et documentation via ces types.
* Validation et documentation via ces types.
- Système d'injection de dépendances.
* Système d'injection de dépendances.
Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement.
Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement.
Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu dASGI), il n'est pas
Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu d'ASGI), il n'est pas
conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic.
conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic.
Le système d'injection de dépendances exige le pré-enregistrement des dépendances et les dépendances sont résolues sur la base des types déclarés. Ainsi, il n'est pas possible de déclarer plus d'un "composant" qui fournit un certain type.
Le système d'injection de dépendances exige le pré-enregistrement des dépendances et les dépendances sont résolues sur la base des types déclarés. Ainsi, il n'est pas possible de déclarer plus d'un « composant » qui fournit un certain type.
Les routes sont déclarées à un seul endroit, en utilisant des fonctions déclarées à d'autres endroits (au lieu
Les routes sont déclarées à un seul endroit, en utilisant des fonctions déclarées à d'autres endroits (au lieu
d'utiliser des décorateurs qui peuvent être placés juste au-dessus de la fonction qui gère l'endpoint). Cette
d'utiliser des décorateurs qui peuvent être placés juste au-dessus de la fonction qui gère l'endpoint). Cette
@ -345,15 +340,15 @@ qui sont relativement fortement couplées.
/// check | A inspiré **FastAPI** à
/// check | A inspiré **FastAPI** à
Définir des validations supplémentaires pour les types de données utilisant la valeur "par défaut" des attributs du modèle. Ceci améliore le support de l'éditeur, et n'était pas disponible dans Pydantic auparavant.
Définir des validations supplémentaires pour les types de données utilisant la valeur « par défaut » des attributs du modèle. Ceci améliore le support de l'éditeur, et n'était pas disponible dans Pydantic auparavant.
Cela a en fait inspiré la mise à jour de certaines parties de Pydantic, afin de supporter le même style de déclaration de validation (toute cette fonctionnalité est maintenant déjà disponible dans Pydantic).
Cela a en fait inspiré la mise à jour de certaines parties de Pydantic, afin de supporter le même style de déclaration de validation (toute cette fonctionnalité est maintenant déjà disponible dans Pydantic).
Hug a été l'un des premiers frameworks à implémenter la déclaration des types de paramètres d'API en utilisant les type hints Python. C'était une excellente idée qui a inspiré d'autres outils à faire de même.
Hug a été l'un des premiers frameworks à implémenter la déclaration des types de paramètres d'API en utilisant les annotations de type Python. C'était une excellente idée qui a inspiré d'autres outils à faire de même.
Il utilisait des types personnalisés dans ses déclarations au lieu des types Python standard, mais c'était tout de même un énorme pas en avant.
Il utilisait des types personnalisés dans ses déclarations au lieu des types Python standard, mais c'était tout de même un énorme pas en avant.
@ -372,28 +367,28 @@ Hug a été créé par Timothy Crosley, le créateur de <a href="https://github.
///
///
/// check | A inspiré **FastAPI** à
/// check | Idées ayant inspiré **FastAPI**
Hug a inspiré certaines parties d'APIStar, et était l'un des outils que je trouvais les plus prometteurs, à côté d'APIStar.
Hug a inspiré certaines parties d'APIStar, et était l'un des outils que je trouvais les plus prometteurs, à côté d'APIStar.
Hug a contribué à inspirer **FastAPI** pour utiliser les type hints Python
Hug a contribué à inspirer **FastAPI** pour utiliser les annotations de type Python
pour déclarer les paramètres, et pour générer automatiquement un schéma définissant l'API.
pour déclarer les paramètres, et pour générer automatiquement un schéma définissant l'API.
Hug a inspiré **FastAPI** pour déclarer un paramètre `response` dans les fonctions pour définir les en-têtes et les cookies.
Hug a inspiré **FastAPI** pour déclarer un paramètre `response` dans les fonctions pour définir les en-têtes et les cookies.
Juste avant de décider de développer **FastAPI**, j'ai trouvé le serveur **APIStar**. Il contenait presque tout ce
Juste avant de décider de développer **FastAPI**, j'ai trouvé le serveur **APIStar**. Il contenait presque tout ce
que je recherchais et avait un beau design.
que je recherchais et avait un beau design.
C'était l'une des premières implémentations d'un framework utilisant les type hints Python pour déclarer les paramètres
C'était l'une des premières implémentations d'un framework utilisant les annotations de type Python pour déclarer les paramètres
et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou moins en même temps que Hug. Mais APIStar utilisait le standard OpenAPI.
et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou moins en même temps que Hug. Mais APIStar utilisait le standard OpenAPI.
Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes type hints à plusieurs endroits.
Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes annotations de type à plusieurs endroits.
La définition du schéma de corps de requête n'utilisait pas les mêmes type hints Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible.
La définition du schéma de corps de requête n'utilisait pas les mêmes annotations de type Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible.
Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette).
Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette).
@ -429,20 +424,20 @@ Et après avoir longtemps cherché un framework similaire et testé de nombreuse
Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**.
Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**.
Je considère **FastAPI** comme un "successeur spirituel" d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents.
Je considère **FastAPI** comme un « successeur spirituel » d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents.
Pydantic est une bibliothèque permettant de définir la validation, la sérialisation et la documentation des données (à l'aide de JSON Schema) en se basant sur les Python type hints.
Pydantic est une bibliothèque permettant de définir la validation, la sérialisation et la documentation des données (à l'aide de JSON Schema) en se basant sur les annotations de type Python.
Cela le rend extrêmement intuitif.
Cela le rend extrêmement intuitif.
Il est comparable à Marshmallow. Bien qu'il soit plus rapide que Marshmallow dans les benchmarks. Et comme il est
Il est comparable à Marshmallow. Bien qu'il soit plus rapide que Marshmallow dans les benchmarks. Et comme il est
basé sur les mêmes type hints Python, le support de l'éditeur est grand.
basé sur les mêmes annotations de type Python, le support de l'éditeur est grand.
/// check | **FastAPI** l'utilise pour
/// check | **FastAPI** l'utilise pour
@ -452,9 +447,9 @@ Gérer toute la validation des données, leur sérialisation et la documentation
Starlette est un framework/toolkit léger <abbrtitle="Le nouveau standard pour construire des applications web asynchrones en Python">ASGI</abbr>, qui est idéal pour construire des services asyncio performants.
Starlette est un framework/toolkit léger <dfntitle="La nouvelle norme pour créer des applications web Python asynchrones">ASGI</dfn>, qui est idéal pour construire des services asyncio performants.
Il est très simple et intuitif. Il est conçu pour être facilement extensible et avoir des composants modulaires.
Il est très simple et intuitif. Il est conçu pour être facilement extensible et avoir des composants modulaires.
@ -462,29 +457,28 @@ Il offre :
- Des performances vraiment impressionnantes.
- Des performances vraiment impressionnantes.
- Le support des WebSockets.
- Le support des WebSockets.
- Le support de GraphQL.
- Les tâches d'arrière-plan.
- Les tâches d'arrière-plan.
- Les événements de démarrage et d'arrêt.
- Les événements de démarrage et d'arrêt.
- Un client de test basé sur request.
- Un client de test basé sur HTTPX.
- CORS, GZip, fichiers statiques, streaming des réponses.
- CORS, GZip, fichiers statiques, streaming des réponses.
- Le support des sessions et des cookies.
- Le support des sessions et des cookies.
- Une couverture de test à 100 %.
- Une couverture de test à 100 %.
- 100 % de la base de code avec des annotations de type.
- 100 % de la base de code avec des annotations de type.
- Zéro forte dépendance à d'autres packages.
- Peu de dépendances strictes.
Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur.
Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur.
Starlette fournit toutes les fonctionnalités de base d'un micro-framework web.
Starlette fournit toutes les fonctionnalités de base d'un micro‑framework web.
Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation.
Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation.
C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basé sur les type hints Python (en utilisant Pydantic). Cela, plus le système d'injection de dépendances, les utilitaires de sécurité, la génération de schémas OpenAPI, etc.
C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basé sur les annotations de type Python (en utilisant Pydantic). Cela, plus le système d'injection de dépendances, les utilitaires de sécurité, la génération de schémas OpenAPI, etc.
/// note | Détails techniques
/// note | Détails techniques
ASGI est une nouvelle "norme" développée par les membres de l'équipe principale de Django. Il ne s'agit pas encore d'une "norme Python" (un PEP), bien qu'ils soient en train de le faire.
ASGI est une nouvelle « norme » développée par les membres de l'équipe principale de Django. Il ne s'agit pas encore d'une « norme Python » (un PEP), bien qu'ils soient en train de le faire.
Néanmoins, il est déjà utilisé comme "standard" par plusieurs outils. Cela améliore grandement l'interopérabilité, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`.
Néanmoins, il est déjà utilisé comme « standard » par plusieurs outils. Cela améliore grandement l'interopérabilité, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`.
///
///
@ -498,7 +492,7 @@ Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire direct
Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
@ -511,12 +505,12 @@ C'est le serveur recommandé pour Starlette et **FastAPI**.
Le serveur web principal pour exécuter les applications **FastAPI**.
Le serveur web principal pour exécuter les applications **FastAPI**.
Vous pouvez le combiner avec Gunicorn, pour avoir un serveur multi-processus asynchrone.
Vous pouvez également utiliser l'option de ligne de commande `--workers` pour avoir un serveur multi‑processus asynchrone.
Pour plus de détails, consultez la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
Pour plus de détails, consultez la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
///
///
## Benchmarks et vitesse
## Benchmarks et vitesse { #benchmarks-and-speed }
Pour comprendre, comparer et voir la différence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=\_blank}.
Pour comprendre, comparer et voir la différence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=_blank}.
# Concurrence et async / await { #concurrency-and-async-await }
Cette page vise à fournir des détails sur la syntaxe `async def` pour les *fonctions de chemins* et quelques rappels sur le code asynchrone, la concurrence et le parallélisme.
Détails sur la syntaxe `async def` pour les *fonctions de chemin d'accès* et quelques rappels sur le code asynchrone, la concurrence et le parallélisme.
## Vous êtes pressés ?
## Vous êtes pressés ? { #in-a-hurry }
<abbrtitle="'too long; didn't read' en anglais, ou 'trop long ; j'ai pas lu'"><strong>TL;DR :</strong></abbr>
<abbrtitle="too long; didn't read - trop long ; pas lu"><strong>TL;DR :</strong></abbr>
Si vous utilisez des bibliothèques tierces qui nécessitent d'être appelées avec `await`, telles que :
Si vous utilisez des bibliothèques tierces qui nécessitent d'être appelées avec `await`, telles que :
```Python
```Python
results = await some_library()
results = await some_library()
```
```
Alors, déclarez vos *fonctions de chemins* avec `async def` comme ceci :
Alors, déclarez vos *fonctions de chemin d'accès* avec `async def` comme ceci :
```Python hl_lines="2"
```Python hl_lines="2"
@app.get('/')
@app.get('/')
@ -20,7 +21,7 @@ async def read_results():
return results
return results
```
```
/// note
/// note | Remarque
Vous pouvez uniquement utiliser `await` dans les fonctions créées avec `async def`.
Vous pouvez uniquement utiliser `await` dans les fonctions créées avec `async def`.
@ -28,7 +29,7 @@ Vous pouvez uniquement utiliser `await` dans les fonctions créées avec `async
---
---
Si vous utilisez une bibliothèque externe qui communique avec quelque chose (une BDD, une API, un système de fichiers, etc.) et qui ne supporte pas l'utilisation d'`await` (ce qui est actuellement le cas pour la majorité des bibliothèques de BDD), alors déclarez vos *fonctions de chemin* normalement, avec le classique `def`, comme ceci :
Si vous utilisez une bibliothèque externe qui communique avec quelque chose (une base de données, une API, le système de fichiers, etc.) et qui ne supporte pas l'utilisation d'`await` (ce qui est actuellement le cas pour la majorité des bibliothèques de base de données), alors déclarez vos *fonctions de chemin d'accès* normalement, avec le classique `def`, comme ceci :
```Python hl_lines="2"
```Python hl_lines="2"
@app.get('/')
@app.get('/')
@ -39,7 +40,7 @@ def results():
---
---
Si votre application n'a pas à communiquer avec une bibliothèque externe et pas à attendre de réponse, utilisez `async def`.
Si votre application n'a pas à communiquer avec une autre chose et à attendre sa réponse, utilisez `async def`, même si vous n'avez pas besoin d'utiliser `await` à l'intérieur.
---
---
@ -47,15 +48,15 @@ Si vous ne savez pas, utilisez seulement `def` comme vous le feriez habituelleme
---
---
**Note** : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin* autant que nécessaire, **FastAPI** saura faire ce qu'il faut avec.
Note : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin d'accès* autant que nécessaire, et définir chacune avec l’option la plus adaptée pour vous. FastAPI fera ce qu'il faut avec elles.
Au final, peu importe le cas parmi ceux ci-dessus, **FastAPI** fonctionnera de manière asynchrone et sera extrêmement rapide.
Au final, peu importe le cas parmi ceux ci-dessus, FastAPI fonctionnera de manière asynchrone et sera extrêmement rapide.
Mais si vous suivez bien les instructions ci-dessus, alors **FastAPI** pourra effectuer quelques optimisations et ainsi améliorer les performances.
Mais si vous suivez bien les instructions ci-dessus, il pourra effectuer quelques optimisations et ainsi améliorer les performances.
## Détails techniques
## Détails techniques { #technical-details }
Les versions modernes de Python supportent le **code asynchrone** grâce aux **"coroutines"** avec les syntaxes **`async` et `await`**.
Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**.
Analysons les différentes parties de cette phrase dans les sections suivantes :
Analysons les différentes parties de cette phrase dans les sections suivantes :
@ -63,46 +64,46 @@ Analysons les différentes parties de cette phrase dans les sections suivantes :
* **`async` et `await`**
* **`async` et `await`**
* **Coroutines**
* **Coroutines**
## Code asynchrone
## Code asynchrone { #asynchronous-code }
Faire du code asynchrone signifie que le langage 💬 est capable de dire à l'ordinateur / au programme 🤖 qu'à un moment du code, il 🤖 devra attendre que *quelque chose d'autre* se termine autre part. Disons que ce *quelque chose d'autre* est appelé "fichier-lent" 📝.
Faire du code asynchrone signifie que le langage 💬 est capable de dire à l'ordinateur / au programme 🤖 qu'à un moment du code, il 🤖 devra attendre que *quelque chose d'autre* se termine autre part. Disons que ce *quelque chose d'autre* est appelé « slow-file » 📝.
Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tâches, pendant que "fichier-lent" 📝 se termine.
Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tâches, pendant que « slow-file » 📝 se termine.
Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance que ce soit parce qu'il attend à nouveau, ou car il 🤖 a fini tout le travail qu'il avait à faire. Il 🤖 regardera donc si les tâches qu'il attend ont terminé d'être effectuées.
Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance que ce soit parce qu'il attend à nouveau, ou car il 🤖 a fini tout le travail qu'il avait à faire. Il 🤖 regardera donc si les tâches qu'il attend ont terminé d'être effectuées.
Ensuite, il 🤖 prendra la première tâche à finir (disons, notre "fichier-lent" 📝) et continuera à faire avec cette dernière ce qu'il était censé.
Ensuite, il 🤖 prendra la première tâche à finir (disons, notre « slow-file » 📝) et continuera à faire avec cette dernière ce qu'il était censé.
Ce "attendre quelque chose d'autre" fait généralement référence à des opérations <abbrtitle="Input/Output ou Entrées et Sorties ">I/O</abbr> qui sont relativement "lentes" (comparées à la vitesse du processeur et de la mémoire RAM) telles qu'attendre que :
Ce « attendre quelque chose d'autre » fait généralement référence à des opérations <abbrtitle="Input and Output - Entrées et sorties">I/O</abbr> qui sont relativement « lentes » (comparées à la vitesse du processeur et de la mémoire RAM) telles qu'attendre que :
* de la donnée soit envoyée par le client à travers le réseau
* de la donnée soit envoyée par le client à travers le réseau
* de la donnée envoyée depuis votre programme soit reçue par le client à travers le réseau
* de la donnée envoyée depuis votre programme soit reçue par le client à travers le réseau
* le contenu d'un fichier sur le disque soit lu par le système et passé à votre programme
* le contenu d'un fichier sur le disque soit lu par le système et passé à votre programme
* le contenu que votre programme a passé au système soit écrit sur le disque
* le contenu que votre programme a passé au système soit écrit sur le disque
* une opération effectuée à distance par une API se termine
* une opération effectuée à distance par une API se termine
* une opération en BDD se termine
* une opération en base de données se termine
* une requête à une BDD renvoie un résultat
* une requête à une base de données renvoie un résultat
* etc.
* etc.
Le temps d'exécution étant consommé majoritairement par l'attente d'opérations <abbrtitle="Input/Output ou Entrées et Sorties ">I/O</abbr> on appelle ceci des opérations <ahref="https://fr.wikipedia.org/wiki/I/O_bound"class="external-link"target="_blank">"I/O bound"</a>.
Le temps d'exécution étant consommé majoritairement par l'attente d'opérations <abbrtitle="Input and Output - Entrées et sorties">I/O</abbr>, on appelle ceci des opérations « I/O bound ».
Ce concept se nomme l'"asynchronisme" car l'ordinateur / le programme n'a pas besoin d'être "synchronisé" avec la tâche, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations.
Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'être « synchronisé » avec la tâche, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations.
À la place, en étant "asynchrone", une fois terminée, une tâche peut légèrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, et revienne récupérer le résultat.
À la place, en étant « asynchrone », une fois terminée, une tâche peut légèrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, et revienne récupérer le résultat.
Pour parler de tâches "synchrones" (en opposition à "asynchrones"), on utilise souvent le terme "séquentiel", car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente.
Pour parler de tâches « synchrones » (en opposition à « asynchrones »), on utilise souvent le terme « séquentiel », car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente.
### Concurrence et Burgers
### Concurrence et Burgers { #concurrency-and-burgers }
L'idée de code **asynchrone** décrite ci-dessus est parfois aussi appelée **"concurrence"**. Ce qui est différent du **"parallélisme"**.
L'idée de code **asynchrone** décrite ci-dessus est parfois aussi appelée **« concurrence »**. Ce qui est différent du **« parallélisme »**.
La **concurrence** et le **parallélisme** sont tous deux liés à l'idée de "différentes choses arrivant plus ou moins au même moment".
La **concurrence** et le **parallélisme** sont tous deux liés à l'idée de « différentes choses arrivant plus ou moins au même moment ».
Mais les détails entre la **concurrence** et le **parallélisme** diffèrent sur de nombreux points.
Mais les détails entre la **concurrence** et le **parallélisme** diffèrent sur de nombreux points.
Pour expliquer la différence, voici une histoire de burgers :
Pour expliquer la différence, voici une histoire de burgers :
#### Burgers concurrents
### Burgers concurrents { #concurrent-burgers }
Vous amenez votre crush 😍 dans votre fast food 🍔 favori, et faites la queue pendant que le serveur 💁 prend les commandes des personnes devant vous.
Vous amenez votre crush 😍 dans votre fast food 🍔 favori, et faites la queue pendant que le serveur 💁 prend les commandes des personnes devant vous.
@ -122,13 +123,13 @@ Le serveur 💁 vous donne le numéro assigné à votre commande.
Pendant que vous attendez, vous allez choisir une table avec votre crush 😍, vous discutez avec votre crush 😍 pendant un long moment (les burgers étant "magnifiques" ils sont très longs à préparer ✨🍔✨).
Pendant que vous attendez, vous allez choisir une table avec votre crush 😍, vous discutez avec votre crush 😍 pendant un long moment (les burgers étant « magnifiques » ils sont très longs à préparer ✨🍔✨).
Pendant que vous êtes assis à table, en attendant que les burgers 🍔 soient prêts, vous pouvez passer ce temps à admirer à quel point votre crush 😍 est géniale, mignonne et intelligente ✨😍✨.
Pendant que vous êtes assis à table, en attendant que les burgers 🍔 soient prêts, vous pouvez passer ce temps à admirer à quel point votre crush 😍 est géniale, mignonne et intelligente ✨😍✨.
Pendant que vous discutez avec votre crush 😍, de temps en temps vous jetez un coup d'oeil au nombre affiché au-dessus du comptoir pour savoir si c'est à votre tour d'être servis.
Pendant que vous discutez avec votre crush 😍, de temps en temps vous jetez un coup d’œil au nombre affiché au-dessus du comptoir pour savoir si c'est à votre tour d'être servis.
Jusqu'au moment où c'est (enfin) votre tour. Vous allez au comptoir, récupérez vos burgers 🍔 et revenez à votre table.
Jusqu'au moment où c'est (enfin) votre tour. Vous allez au comptoir, récupérez vos burgers 🍔 et revenez à votre table.
@ -148,23 +149,23 @@ Illustrations proposées par <a href="https://www.instagram.com/ketrinadrawsalot
Imaginez que vous êtes l'ordinateur / le programme 🤖 dans cette histoire.
Imaginez que vous êtes l'ordinateur / le programme 🤖 dans cette histoire.
Pendant que vous faites la queue, vous être simplement inactif 😴, attendant votre tour, ne faisant rien de "productif". Mais la queue est rapide car le serveur 💁 prend seulement les commandes (et ne les prépare pas), donc tout va bien.
Pendant que vous faites la queue, vous être simplement inactif 😴, attendant votre tour, ne faisant rien de « productif ». Mais la queue est rapide car le serveur 💁 prend seulement les commandes (et ne les prépare pas), donc tout va bien.
Ensuite, quand c'est votre tour, vous faites des actions "productives" 🤓, vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush 😍 son choix, payez 💸, vérifiez que vous utilisez la bonne carte de crédit, vérifiez que le montant débité sur la carte est correct, vérifiez que la commande contient les bons produits, etc.
Ensuite, quand c'est votre tour, vous faites des actions « productives » 🤓, vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush 😍 son choix, payez 💸, vérifiez que vous utilisez la bonne carte de crédit, vérifiez que le montant débité sur la carte est correct, vérifiez que la commande contient les bons produits, etc.
Mais ensuite, même si vous n'avez pas encore vos burgers 🍔, votre travail avec le serveur 💁 est "en pause" ⏸, car vous devez attendre 🕙 que vos burgers soient prêts.
Mais ensuite, même si vous n'avez pas encore vos burgers 🍔, votre travail avec le serveur 💁 est « en pause » ⏸, car vous devez attendre 🕙 que vos burgers soient prêts.
Après vous être écarté du comptoir et vous être assis à votre table avec le numéro de votre commande, vous pouvez tourner 🔀 votre attention vers votre crush 😍, et "travailler" ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de "productif" 🤓, vous flirtez avec votre crush 😍.
Après vous être écarté du comptoir et vous être assis à votre table avec le numéro de votre commande, vous pouvez tourner 🔀 votre attention vers votre crush 😍, et « travailler » ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de « productif » 🤓, vous flirtez avec votre crush 😍.
Puis le serveur 💁 dit "J'ai fini de préparer les burgers" 🍔 en mettant votre numéro sur l'affichage du comptoir, mais vous ne courrez pas immédiatement au moment où votre numéro s'affiche. Vous savez que personne ne volera vos burgers 🍔 car vous avez votre numéro et les autres clients ont le leur.
Puis le serveur 💁 dit « J'ai fini de préparer les burgers » 🍔 en mettant votre numéro sur l'affichage du comptoir, mais vous ne courez pas immédiatement au moment où votre numéro s'affiche. Vous savez que personne ne volera vos burgers 🍔 car vous avez votre numéro et les autres clients ont le leur.
Vous attendez donc que votre crush 😍 finisse son histoire, souriez gentiment et dites que vous allez chercher les burgers ⏸.
Vous attendez donc que votre crush 😍 finisse son histoire, souriez gentiment et dites que vous allez chercher les burgers ⏸.
Pour finir vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers 🍔, remerciez le serveur et ramenez les burgers 🍔 à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite, crée une nouvelle tâche de "manger les burgers" 🔀 ⏯, mais la précédente, "récupérer les burgers" est terminée ⏹.
Pour finir vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers 🍔, remerciez le serveur et ramenez les burgers 🍔 à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite, crée une nouvelle tâche de « manger les burgers » 🔀 ⏯, mais la précédente, « récupérer les burgers » est terminée ⏹.
#### Burgers parallèles
### Burgers parallèles { #parallel-burgers }
Imaginons désormais que ce ne sont pas des "burgers concurrents" mais des "burgers parallèles".
Imaginons désormais que ce ne sont pas des « burgers concurrents » mais des « burgers parallèles ».
Vous allez avec votre crush 😍 dans un fast food 🍔 parallélisé.
Vous allez avec votre crush 😍 dans un fast food 🍔 parallélisé.
@ -188,7 +189,7 @@ Vous attendez devant le comptoir afin que personne ne prenne vos burgers 🍔 av
Vous et votre crush 😍 étant occupés à vérifier que personne ne passe devant vous prendre vos burgers au moment où ils arriveront 🕙, vous ne pouvez pas vous préoccuper de votre crush 😞.
Vous et votre crush 😍 étant occupés à vérifier que personne ne passe devant vous prendre vos burgers au moment où ils arriveront 🕙, vous ne pouvez pas vous préoccuper de votre crush 😞.
C'est du travail "synchrone", vous être "synchronisés" avec le serveur/cuisinier 👨🍳. Vous devez attendre 🕙 et être présent au moment exact où le serveur/cuisinier 👨🍳 finira les burgers 🍔 et vous les donnera, sinon quelqu'un risque de vous les prendre.
C'est du travail « synchrone », vous être « synchronisés » avec le serveur/cuisinier 👨🍳. Vous devez attendre 🕙 et être présent au moment exact où le serveur/cuisinier 👨🍳 finira les burgers 🍔 et vous les donnera, sinon quelqu'un risque de vous les prendre.
@ -212,7 +213,7 @@ Illustrations proposées par <a href="https://www.instagram.com/ketrinadrawsalot
---
---
Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush 😍) attendant 🕙 à deux et dédiant votre attention 🕙 à "attendre devant le comptoir" pour une longue durée.
Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush 😍) attendant 🕙 à deux et dédiant votre attention ⏯ à « attendre devant le comptoir » 🕙 pour une longue durée.
Le fast-food a 8 processeurs (serveurs/cuisiniers) 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳. Alors que le fast-food de burgers concurrents en avait 2 (un serveur et un cuisinier).
Le fast-food a 8 processeurs (serveurs/cuisiniers) 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳. Alors que le fast-food de burgers concurrents en avait 2 (un serveur et un cuisinier).
@ -222,7 +223,7 @@ Et pourtant l'expérience finale n'est pas meilleure 😞.
C'est donc l'histoire équivalente parallèle pour les burgers 🍔.
C'est donc l'histoire équivalente parallèle pour les burgers 🍔.
Pour un exemple plus courant dans la "vie réelle", imaginez une banque.
Pour un exemple plus courant dans la « vie réelle », imaginez une banque.
Jusqu'à récemment, la plupart des banques avaient plusieurs caisses (et banquiers) 👨💼👨💼👨💼👨💼 et une unique file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙.
Jusqu'à récemment, la plupart des banques avaient plusieurs caisses (et banquiers) 👨💼👨💼👨💼👨💼 et une unique file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙.
@ -232,9 +233,9 @@ Et vous deviez attendre 🕙 dans la file pendant un long moment ou vous perdiez
Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous à la banque 🏦.
Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous à la banque 🏦.
#### Conclusion
### Conclusion sur les burgers { #burger-conclusion }
Dans ce scénario des "burgers du fast-food avec votre crush", comme il y a beaucoup d'attente 🕙, il est très logique d'avoir un système concurrent ⏸🔀⏯.
Dans ce scénario des « burgers du fast-food avec votre crush », comme il y a beaucoup d'attente 🕙, il est très logique d'avoir un système concurrent ⏸🔀⏯.
Et c'est le cas pour la plupart des applications web.
Et c'est le cas pour la plupart des applications web.
@ -242,17 +243,17 @@ Vous aurez de nombreux, nombreux utilisateurs, mais votre serveur attendra 🕙
Puis vous attendrez 🕙 de nouveau que leurs réponses reviennent.
Puis vous attendrez 🕙 de nouveau que leurs réponses reviennent.
Cette "attente" 🕙 se mesure en microsecondes, mais tout de même, en cumulé cela fait beaucoup d'attente.
Cette « attente » 🕙 se mesure en microsecondes, mais tout de même, en cumulé cela fait beaucoup d'attente.
C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web.
C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web.
Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force du Go en tant que langage de programmation.
Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force de Go en tant que langage de programmation.
Et c'est le même niveau de performance que celui obtenu avec **FastAPI**.
Et c'est le même niveau de performance que celui obtenu avec **FastAPI**.
Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps, on obtient des performances plus hautes que la plupart des frameworks NodeJS et égales à celles du Go, qui est un langage compilé plus proche du C <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(tout ça grâce à Starlette)</a>.
Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps, on obtient des performances plus hautes que la plupart des frameworks NodeJS testés et égales à celles du Go, qui est un langage compilé plus proche du C <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(tout ça grâce à Starlette)</a>.
### Est-ce que la concurrence est mieux que le parallélisme ?
### Est-ce que la concurrence est mieux que le parallélisme ? { #is-concurrency-better-than-parallelism }
Nope ! C'est ça la morale de l'histoire.
Nope ! C'est ça la morale de l'histoire.
@ -276,11 +277,11 @@ Mais dans ce cas, si pouviez amener 8 ex-serveurs/cuisiniers/devenus-nettoyeurs
Dans ce scénario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail.
Dans ce scénario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail.
Et comme la plupart du temps d'exécution est pris par du "vrai" travail (et non de l'attente), et que le travail dans un ordinateur est fait par un <abbrtitle="Central Processing Unit">CPU</abbr>, ce sont des problèmes dits "CPU bound".
Et comme la plupart du temps d'exécution est pris par du « vrai » travail (et non de l'attente), et que le travail dans un ordinateur est fait par un <abbrtitle="Central Processing Unit - Unité centrale de traitement">CPU</abbr>, ce sont des problèmes dits « CPU bound ».
---
---
Des exemples communs d'opérations "CPU bounds" sont les procédés qui requièrent des traitements mathématiques complexes.
Des exemples communs d'opérations « CPU bound » sont les procédés qui requièrent des traitements mathématiques complexes.
Par exemple :
Par exemple :
@ -289,19 +290,19 @@ Par exemple :
* L'apprentissage automatique (ou **Machine Learning**) : cela nécessite de nombreuses multiplications de matrices et vecteurs. Imaginez une énorme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au même moment.
* L'apprentissage automatique (ou **Machine Learning**) : cela nécessite de nombreuses multiplications de matrices et vecteurs. Imaginez une énorme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au même moment.
* L'apprentissage profond (ou **Deep Learning**) : est un sous-domaine du **Machine Learning**, donc les mêmes raisons s'appliquent. Avec la différence qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles.
* L'apprentissage profond (ou **Deep Learning**) : est un sous-domaine du **Machine Learning**, donc les mêmes raisons s'appliquent. Avec la différence qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles.
### Concurrence + Parallélisme : Web + Machine Learning
Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (c'est l'attrait principal de NodeJS).
Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (c'est l'attrait principal de NodeJS).
Mais vous pouvez aussi profiter du parallélisme et multiprocessing afin de gérer des charges **CPU bound** qui sont récurrentes dans les systèmes de *Machine Learning*.
Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallèle) afin de gérer des charges **CPU bound** qui sont récurrentes dans les systèmes de *Machine Learning*.
Ça, ajouté au fait que Python soit le langage le plus populaire pour la **Data Science**, le **Machine Learning** et surtout le **Deep Learning**, font de **FastAPI** un très bon choix pour les APIs et applications de **Data Science** / **Machine Learning**.
Ça, ajouté au fait que Python soit le langage le plus populaire pour la **Data Science**, le **Machine Learning** et surtout le **Deep Learning**, font de **FastAPI** un très bon choix pour les APIs et applications de **Data Science** / **Machine Learning**.
Pour comprendre comment mettre en place ce parallélisme en production, allez lire la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
Pour comprendre comment mettre en place ce parallélisme en production, allez lire la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
## `async` et `await`
## `async` et `await` { #async-and-await }
Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone, tout en gardant une apparence de code "séquentiel" classique en laissant Python faire l'attente pour vous au bon moment.
Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone, tout en gardant une apparence de code « séquentiel » classique en laissant Python faire l'attente pour vous au bon moment.
Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'utiliser comme tel :
Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'utiliser comme tel :
Donc, si vous utilisez une bibliothèque qui nécessite que ses fonctions soient appelées avec `await`, vous devez définir la *fonction de chemin* en utilisant `async def` comme dans :
Donc, si vous utilisez une bibliothèque qui nécessite que ses fonctions soient appelées avec `await`, vous devez définir la *fonction de chemin d'accès* en utilisant `async def` comme dans :
```Python hl_lines="2-3"
```Python hl_lines="2-3"
@app.get('/burgers')
@app.get('/burgers')
@ -348,52 +349,61 @@ async def read_burgers():
return burgers
return burgers
```
```
### Plus de détails techniques
### Plus de détails techniques { #more-technical-details }
Vous avez donc compris que `await` peut seulement être utilisé dans des fonctions définies avec `async def`.
Vous avez donc compris que `await` peut seulement être utilisé dans des fonctions définies avec `async def`.
Mais en même temps, les fonctions définies avec `async def` doivent être appelées avec `await` et donc dans des fonctions définies elles aussi avec `async def`.
Mais en même temps, les fonctions définies avec `async def` doivent être appelées avec `await` et donc dans des fonctions définies elles aussi avec `async def`.
Vous avez donc remarqué ce paradoxe d'oeuf et de la poule, comment appelle-t-on la première fonction `async` ?
Vous avez donc remarqué ce paradoxe d'œuf et de la poule, comment appelle-t-on la première fonction `async` ?
Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « première » fonction sera votre *fonction de chemin d'accès* ; et **FastAPI** saura comment arriver au résultat attendu.
Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez également le faire.
Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette "première" fonction sera votre *fonction de chemin* ; et **FastAPI** saura comment arriver au résultat attendu.
Mais si vous utilisez `async` / `await` sans **FastAPI**, <ahref="https://docs.python.org/3/library/asyncio-task.html#coroutine"class="external-link"target="_blank">allez jetez un coup d'oeil à la documentation officielle de Python</a>.
Starlette (et **FastAPI**) s’appuie sur <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a>, ce qui le rend compatible à la fois avec la bibliothèque standard<ahref="https://docs.python.org/3/library/asyncio-task.html"class="external-link"target="_blank">asyncio</a> de Python et avec <ahref="https://trio.readthedocs.io/en/stable/"class="external-link"target="_blank">Trio</a>.
### Autres formes de code asynchrone
En particulier, vous pouvez utiliser directement <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> pour vos cas d’usage de concurrence avancés qui nécessitent des schémas plus élaborés dans votre propre code.
Et même si vous n’utilisiez pas FastAPI, vous pourriez aussi écrire vos propres applications async avec <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> pour une grande compatibilité et pour bénéficier de ses avantages (par ex. la « structured concurrency »).
J’ai créé une autre bibliothèque au-dessus d’AnyIO, comme une fine surcouche, pour améliorer un peu les annotations de type et obtenir une meilleure **autocomplétion**, des **erreurs en ligne**, etc. Elle propose également une introduction et un tutoriel accessibles pour vous aider à **comprendre** et écrire **votre propre code async** : <ahref="https://asyncer.tiangolo.com/"class="external-link"target="_blank">Asyncer</a>. Elle sera particulièrement utile si vous devez **combiner du code async avec du code classique** (bloquant/synchrone).
### Autres formes de code asynchrone { #other-forms-of-asynchronous-code }
L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage.
L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage.
Mais cela rend la programmation asynchrone bien plus simple.
Mais cela rend la programmation asynchrone bien plus simple.
Cette même syntaxe (ou presque) était aussi incluse dans les versions modernes de Javascript (dans les versions navigateur et NodeJS).
Cette même syntaxe (ou presque) a aussi été incluse récemment dans les versions modernes de JavaScript (dans les navigateurs et NodeJS).
Mais avant ça, gérer du code asynchrone était bien plus complexe et difficile.
Mais avant ça, gérer du code asynchrone était bien plus complexe et difficile.
Dans les versions précédentes de Python, vous auriez utilisé des *threads* ou <ahref="https://www.gevent.org/"class="external-link"target="_blank">Gevent</a>. Mais le code aurait été bien plus difficile à comprendre, débugger, et concevoir.
Dans les versions précédentes de Python, vous auriez utilisé des threads ou <ahref="https://www.gevent.org/"class="external-link"target="_blank">Gevent</a>. Mais le code aurait été bien plus difficile à comprendre, débugger, et concevoir.
Dans les versions précédentes de Javascript NodeJS / Navigateur, vous auriez utilisé des "callbacks". Menant potentiellement à ce que l'on appelle le "callback hell".
Dans les versions précédentes de JavaScript côté navigateur / NodeJS, vous auriez utilisé des « callbacks ». Menant potentiellement à ce que l'on appelle le « callback hell ».
## Coroutines
## Coroutines { #coroutines }
**Coroutine** est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction classique qui va démarrer à un moment et terminer à un autre, mais qu'elle peut aussi être mise en pause ⏸, du moment qu'il y a un `await` dans son contenu.
« Coroutine » est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction classique qui va démarrer à un moment et terminer à un autre, mais qu'elle peut aussi être mise en pause ⏸, du moment qu'il y a un `await` dans son contenu.
Mais toutes ces fonctionnalités d'utilisation de code asynchrone avec `async` et `await` sont souvent résumées comme l'utilisation des *coroutines*. On peut comparer cela à la principale fonctionnalité clé de Go, les "Goroutines".
Mais toutes ces fonctionnalités d'utilisation de code asynchrone avec `async` et `await` sont souvent résumées comme l'utilisation des « coroutines ». On peut comparer cela à la principale fonctionnalité clé de Go, les « Goroutines ».
## Conclusion
## Conclusion { #conclusion }
Reprenons la phrase du début de la page :
Reprenons la phrase du début de la page :
> Les versions modernes de Python supportent le **code asynchrone** grâce aux **"coroutines"** avec les syntaxes **`async` et `await`**.
> Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**.
Ceci devrait être plus compréhensible désormais. ✨
Ceci devrait être plus compréhensible désormais. ✨
Tout ceci est donc ce qui donne sa force à **FastAPI** (à travers Starlette) et lui permet d'avoir des performances aussi impressionnantes.
Tout ceci est donc ce qui donne sa force à FastAPI (à travers Starlette) et lui permet d'avoir une performance aussi impressionnante.
## Détails très techniques
## Détails très techniques { #very-technical-details }
/// warning | Attention !
/// warning | Alertes
Vous pouvez probablement ignorer cela.
Vous pouvez probablement ignorer cela.
@ -403,32 +413,32 @@ Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloqu
///
///
### Fonctions de chemin
### Fonctions de chemin d'accès { #path-operation-functions }
Quand vous déclarez une *fonction de chemin* avec un `def` normal et non `async def`, elle est exécutée dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutôt que d'être appelée directement (car cela bloquerait le serveur).
Quand vous déclarez une *fonction de chemin d'accès* avec un `def` normal et non `async def`, elle est exécutée dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutôt que d'être appelée directement (car cela bloquerait le serveur).
Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la façon décrite ci-dessus et que vous êtes habitués à définir des *fonctions de chemin* basiques avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que votre *fonction de chemin* utilise du code qui effectue des opérations <abbrtitle="Input/Output ou Entrées et Sorties ">I/O</abbr> bloquantes.
Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la façon décrite ci-dessus et que vous êtes habitué à définir des *fonctions de chemin d'accès* basiques et purement calculatoires avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que votre *fonction de chemin d'accès* utilise du code qui effectue des opérations <abbrtitle="Input/Output - Entrées/Sorties: lecture ou écriture sur le disque, communications réseau.">I/O</abbr> bloquantes.
Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de même [plus rapide](index.md#performance){.internal-link target=_blank} que (ou au moins de vitesse égale à) votre framework précédent.
Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de même [plus rapide](index.md#performance){.internal-link target=_blank} que (ou au moins de vitesse égale à) votre framework précédent.
### Dépendances
### Dépendances { #dependencies }
La même chose s'applique aux dépendances. Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe.
La même chose s'applique aux [dépendances](tutorial/dependencies/index.md){.internal-link target=_blank}. Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe.
### Sous-dépendances
### Sous-dépendances { #sub-dependencies }
Vous pouvez avoir de multiples dépendances et sous-dépendances dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être "attendues".
Vous pouvez avoir de multiples dépendances et [sous-dépendances](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin d'accès*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être « attendues ».
### Autres fonctions utilitaires
### Autres fonctions utilitaires { #other-utility-functions }
Toute autre fonction utilitaire que vous appelez directement peut être créée avec un classique `def` ou avec `async def` et **FastAPI** n'aura pas d'impact sur la façon dont vous l'appelez.
Toute autre fonction utilitaire que vous appelez directement peut être créée avec un classique `def` ou avec `async def` et FastAPI n'aura pas d'impact sur la façon dont vous l'appelez.
Contrairement aux fonctions que **FastAPI** appelle pour vous : les *fonctions de chemin* et dépendances.
Contrairement aux fonctions que FastAPI appelle pour vous : les *fonctions de chemin d'accès* et dépendances.
Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool, si la fonction est définie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer à la suite du code.
Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer à la suite du code.
---
---
Encore une fois, ce sont des détails très techniques qui peuvent être utiles si vous venez ici les chercher.
Encore une fois, ce sont des détails très techniques qui peuvent être utiles si vous venez ici les chercher.
Sinon, les instructions de la section <ahref="#vous-etes-presses">Vous êtes pressés ?</a> ci-dessus sont largement suffisantes.
Sinon, les instructions de la section <ahref="#in-a-hurry">Vous êtes pressés ?</a> ci-dessus sont largement suffisantes.
@ -14,7 +14,7 @@ Vous êtes pressé et vous connaissez déjà tout ça ? Allez directement au [`D
<summary>Aperçu du Dockerfile 👀</summary>
<summary>Aperçu du Dockerfile 👀</summary>
```Dockerfile
```Dockerfile
FROM python:3.9
FROM python:3.14
WORKDIR /code
WORKDIR /code
@ -166,7 +166,7 @@ Maintenant, dans le même répertoire de projet, créez un fichier `Dockerfile`
```{ .dockerfile .annotate }
```{ .dockerfile .annotate }
# (1)!
# (1)!
FROM python:3.9
FROM python:3.14
# (2)!
# (2)!
WORKDIR /code
WORKDIR /code
@ -390,7 +390,7 @@ Si votre FastAPI est un seul fichier, par exemple `main.py` sans répertoire `./
Vous n'auriez alors qu'à changer les chemins correspondants pour copier le fichier dans le `Dockerfile` :
Vous n'auriez alors qu'à changer les chemins correspondants pour copier le fichier dans le `Dockerfile` :
```{ .dockerfile .annotate hl_lines="10 13" }
```{ .dockerfile .annotate hl_lines="10 13" }
FROM python:3.9
FROM python:3.14
WORKDIR /code
WORKDIR /code
@ -454,7 +454,7 @@ Sans utiliser de conteneurs, faire en sorte que les applications s'exécutent au
## Réplication - Nombre de processus { #replication-number-of-processes }
## Réplication - Nombre de processus { #replication-number-of-processes }
Si vous avez un <abbrtitle="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.
Si vous avez un <dfntitle="Groupe de machines configurées pour être connectées et fonctionner ensemble d'une certaine manière.">cluster</dfn> 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**.
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**.
@ -499,7 +499,7 @@ Bien sûr, il existe des **cas particuliers** où vous pourriez vouloir avoir **
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 :
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 :
@ -65,7 +65,7 @@ Voici un exemple de ce à quoi pourrait ressembler une API HTTPS, étape par ét
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).
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**<abbrtitle="Qui ne change pas">fixe</abbr>.
Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP publique <dfntitle="Ne change pas dans le temps. Pas dynamique.">fixe</dfn>.
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**.
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**.
## Fonctionnalités de FastAPI { #fastapi-features }
**FastAPI** vous offre ceci:
**FastAPI** vous offre les éléments suivants :
### Basé sur des standards ouverts
### Basé sur des standards ouverts { #based-on-open-standards }
* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> pour la création d'API, incluant la déclaration de <abbrtitle="en français: routes. Aussi connu sous le nom anglais endpoints ou routes">path</abbr><abbrtitle="Aussi connu sous le nom de méthodes HTTP. À savoir POST, GET, PUT, DELETE">operations</abbr>, paramètres, corps de requêtes, sécurité, etc.
* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> pour la création d'API, incluant la déclaration de <dfntitle="aussi connu comme : endpoints, routes">chemin</dfn><dfntitle="aussi connu comme méthodes HTTP, comme POST, GET, PUT, DELETE">opérations</dfn>, paramètres, corps de requêtes, sécurité, etc.
* Documentation automatique des modèles de données avec <ahref="http://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> (comme OpenAPI est aussi basée sur JSON Schema).
* Documentation automatique des modèles de données avec <ahref="https://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> (puisque OpenAPI est lui-même basé sur JSON Schema).
* Conçue avec ces standards après une analyse méticuleuse. Plutôt qu'en rajoutant des surcouches après coup.
* Conçu autour de ces standards, après une étude méticuleuse. Plutôt qu'une couche ajoutée après coup.
* Cela permet d'utiliser de la **génération automatique de code client** dans beaucoup de langages.
* Cela permet également d'utiliser la **génération automatique de code client** dans de nombreux langages.
### Documentation automatique
### Documentation automatique { #automatic-docs }
Documentation d'API interactive et interface web d'exploration. Comme le framework est basé sur OpenAPI, de nombreuses options sont disponibles. Deux d'entre-elles sont incluses par défaut.
Documentation d'API interactive et interfaces web d'exploration. Comme le framework est basé sur OpenAPI, plusieurs options existent, 2 incluses par défaut.
* <ahref="https://github.com/swagger-api/swagger-ui"class="external-link"target="_blank"><strong>Swagger UI</strong></a>, propose une documentation interactive. Vous permet de directement tester l'API depuis votre navigateur.
* <ahref="https://github.com/swagger-api/swagger-ui"class="external-link"target="_blank"><strong>Swagger UI</strong></a>, avec exploration interactive, appelez et testez votre API directement depuis le navigateur.
* Une autre documentation d'API est fournie par<ahref="https://github.com/Rebilly/ReDoc"class="external-link"target="_blank"><strong>ReDoc</strong></a>.
* Documentation d'API alternative avec<ahref="https://github.com/Rebilly/ReDoc"class="external-link"target="_blank"><strong>ReDoc</strong></a>.
### Uniquement du Python moderne { #just-modern-python }
Tout est basé sur la déclaration de type standard de **Python 3.8** (grâce à Pydantic). Pas de nouvelles syntaxes à apprendre. Juste du Python standard et moderne.
Tout est basé sur les déclarations de **types Python** standard (grâce à Pydantic). Aucune nouvelle syntaxe à apprendre. Juste du Python moderne standard.
Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (même si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}.
Si vous avez besoin d'un rappel de 2 minutes sur l'utilisation des types en Python (même si vous n'utilisez pas FastAPI), consultez le court tutoriel : [Types Python](python-types.md){.internal-link target=_blank}.
Vous écrivez du python standard avec des annotations de types:
Vous écrivez du Python standard avec des types :
```Python
```Python
from datetime import date
from datetime import date
from pydantic import BaseModel
from pydantic import BaseModel
# Déclare une variable comme étant une str
# Déclarez une variable comme étant une str
# et profitez de l'aide de votre IDE dans cette fonction
# et profitez de l'aide de l'éditeur dans cette fonction
def main(user_id: str):
def main(user_id: str):
return user_id
return user_id
@ -48,7 +48,8 @@ class User(BaseModel):
name: str
name: str
joined: date
joined: date
```
```
Qui peuvent ensuite être utilisés comme cela:
Qui peuvent ensuite être utilisés comme ceci :
```Python
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
@ -64,138 +65,137 @@ my_second_user: User = User(**second_user_data)
/// info
/// info
`**second_user_data` signifie:
`**second_user_data` signifie:
Utilise les clés et valeurs du dictionnaire `second_user_data` directement comme des arguments clé-valeur. C'est équivalent à: `User(id=4, name="Mary", joined="2018-11-30")`
Passez les clés et valeurs du dictionnaire `second_user_data` directement comme arguments clé-valeur, équivalent à : `User(id=4, name="Mary", joined="2018-11-30")`
///
///
### Support d'éditeurs
### Support des éditeurs { #editor-support }
Tout le framework a été conçu pour être facile et intuitif d'utilisation, toutes les décisions de design ont été testées sur de nombreux éditeurs avant même de commencer le développement final afin d'assurer la meilleure expérience de développement possible.
Tout le framework a été conçu pour être facile et intuitif à utiliser, toutes les décisions ont été testées sur plusieurs éditeurs avant même de commencer le développement, pour assurer la meilleure expérience de développement.
Dans le dernier sondage effectué auprès de développeurs python il était clair que<ahref="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features"class="external-link"target="_blank">la fonctionnalité la plus utilisée est "l’autocomplétion"</a>.
Dans les enquêtes auprès des développeurs Python, il est clair<ahref="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features"class="external-link"target="_blank">que l’une des fonctionnalités les plus utilisées est « autocomplétion »</a>.
Tout le framework **FastAPI** a été conçu avec cela en tête. L'autocomplétion fonctionne partout.
L'ensemble du framework **FastAPI** est conçu pour satisfaire cela. L'autocomplétion fonctionne partout.
Vous devrez rarement revenir à la documentation.
Vous aurez rarement besoin de revenir aux documents.
Voici comment votre éditeur peut vous aider:
Voici comment votre éditeur peut vous aider:
* dans <ahref="https://code.visualstudio.com/"class="external-link"target="_blank">Visual Studio Code</a>:
* dans <ahref="https://code.visualstudio.com/"class="external-link"target="_blank">Visual Studio Code</a>:
Vous aurez des propositions de complétion que vous n'auriez jamais imaginées. Par exemple la clé `prix` dans le corps d'un document JSON (qui est peut-être imbriqué) venant d'une requête.
Vous obtiendrez de l'autocomplétion dans du code que vous auriez pu considérer impossible auparavant. Par exemple, la clé `price` à l'intérieur d'un corps JSON (qui aurait pu être imbriqué) provenant d'une requête.
Plus jamais vous ne vous tromperez en tapant le nom d'une clé, vous ne ferez des aller-retour entre votre code et la documentation ou vous ne scrollerez de haut en bas afin d'enfin savoir si vous devez taper`username` ou `user_name`.
Fini de taper des noms de clés erronés, de faire des allers-retours entre les documents, ou de faire défiler vers le haut et vers le bas pour savoir si vous avez finalement utilisé`username` ou `user_name`.
### Court
### Court { #short }
Des **valeurs par défaut** sont définies pour tout, des configurations optionnelles sont présentent partout. Tous ces paramètres peuvent être ajustés afin de faire ce que vous voulez et définir l'API dont vous avez besoin.
Des **valeurs par défaut** sensées pour tout, avec des configurations optionnelles partout. Tous les paramètres peuvent être ajustés finement pour faire ce dont vous avez besoin et définir l'API dont vous avez besoin.
Mais, **tout fonctionne** par défaut.
Mais par défaut, tout **« just works »**.
### Validation
### Validation { #validation }
* Validation pour la plupart (ou tous?) les **types de données** Python incluant:
* Validation pour la plupart (ou tous ?) des **types de données** Python, y compris :
* objets JSON (`dict`).
* objets JSON (`dict`).
* listes JSON (`list`) définissant des types d'éléments.
* tableaux JSON (`list`) définissant les types d'éléments.
* Champs String (`str`), définition de longueur minimum ou maximale.
* champs String (`str`), définition des longueurs minimale et maximale.
* Nombres (`int`, `float`) avec valeur minimale and maximale, etc.
* nombres (`int`, `float`) avec valeurs minimale et maximale, etc.
* Validation pour des types plus exotiques, tel que:
* Validation pour des types plus exotiques, comme :
* URL.
* URL.
* Email.
* Email.
* UUID.
* UUID.
* ...et autres.
* ...et autres.
Toutes les validations sont gérées par le bien établi et robuste **Pydantic**.
Toutes les validations sont gérées par le **Pydantic** bien établi et robuste.
### Sécurité et authentification
### Sécurité et authentification { #security-and-authentication }
La sécurité et l'authentification sont intégrées. Sans aucun compromis avec les bases de données ou les modèles de données.
Sécurité et authentification intégrées. Sans aucun compromis avec les bases de données ou les modèles de données.
Tous les protocoles de sécurités sont définis dans OpenAPI, incluant:
Tous les schémas de sécurité définis dans OpenAPI, y compris :
* HTTP Basic.
* HTTP Basic.
* **OAuth2** (aussi avec **JWT tokens**). Jetez un oeil au tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* **OAuth2** (également avec des **tokens JWT**). Consultez le tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* Clés d'API dans:
* Clés d'API dans:
* Le header.
* les en-têtes.
* Les paramètres de requêtes.
* les paramètres de requête.
* Les cookies, etc.
* les cookies, etc.
Plus toutes les fonctionnalités de sécurités venant de Starlette (incluant les **cookies de sessions**).
Plus toutes les fonctionnalités de sécurité de Starlette (y compris les **cookies de session**).
Le tout conçu en composant réutilisable facilement intégrable à vos systèmes, data stores, base de données relationnelle ou NoSQL, etc.
Le tout construit comme des outils et composants réutilisables, faciles à intégrer à vos systèmes, magasins de données, bases de données relationnelles et NoSQL, etc.
### Injection de dépendances
### Injection de dépendances { #dependency-injection }
FastAPI contient un système simple mais extrêmement puissant d'<abbrtitle='aussi connus sous le nom de "composants", "ressources", "services", "providers"'><strong>Injection de Dépendances</strong></abbr>.
FastAPI inclut un système d’<dfntitle='aussi connu sous le nom de « composants », « ressources », « services », « fournisseurs »'><strong>Injection de dépendances</strong></dfn> extrêmement simple à utiliser, mais extrêmement puissant.
* Même les dépendances peuvent avoir des dépendances, créant une hiérarchie ou un **"graph" de dépendances**
* Même les dépendances peuvent avoir des dépendances, créant une hiérarchie ou un **« graphe » de dépendances**.
* Tout est **automatiquement géré** par le framework
* Le tout **géré automatiquement** par le framework.
* Toutes les dépendances peuvent exiger des données d'une requêtes et **Augmenter les contraintes d'un path operation** et de la documentation automatique.
* Toutes les dépendances peuvent exiger des données des requêtes et **augmenter les contraintes du chemin d'accès** ainsi que la documentation automatique.
* **Validation automatique** même pour les paramètres de *path operation* définis dans les dépendances.
* **Validation automatique** même pour les paramètres de *chemin d'accès* définis dans les dépendances.
* Supporte les systèmes d'authentification d'utilisateurs complexes, les **connexions de base de données**, etc.
* Prise en charge des systèmes d'authentification d'utilisateurs complexes, des **connexions de base de données**, etc.
* **Aucun compromis** avec les bases de données, les frontends, etc. Mais une intégration facile avec n'importe lequel d'entre eux.
* **Aucun compromis** avec les bases de données, les frontends, etc. Mais une intégration facile avec tous.
Ou, en d'autres termes, pas besoin d'eux, importez le code que vous voulez et utilisez le.
Ou, autrement dit, pas besoin d'eux, importez et utilisez le code dont vous avez besoin.
Tout intégration est conçue pour être si simple à utiliser (avec des dépendances) que vous pouvez créer un "plug-in" pour votre application en deux lignes de code utilisant la même syntaxe que celle de vos *path operations*
Toute intégration est conçue pour être si simple à utiliser (avec des dépendances) que vous pouvez créer un « plug-in » pour votre application en 2 lignes de code en utilisant la même structure et la même syntaxe que pour vos *chemins d'accès*.
### Testé
### Testé { #tested }
* 100% <abbrtitle="La quantité de code qui est testé automatiquement">de couverture de test</abbr>.
* 100 % de <dfntitle="La quantité de code testée automatiquement">couverture de test</dfn>.
* 100% <abbrtitle="Annotation de types Python, avec cela votre éditeur et autres outils externes peuvent vous fournir un meilleur support">d'annotations de type</abbr> dans le code.
* 100 % de base de code <dfntitle="Annotations de type Python ; avec cela votre éditeur et les outils externes peuvent vous offrir un meilleur support">annotée avec des types</dfn>.
* Utilisé dans des applications mises en production.
* Utilisé dans des applications en production.
## Fonctionnalités de Starlette
## Fonctionnalités de Starlette { #starlette-features }
**FastAPI** est complètement compatible (et basé sur) <ahref="https://www.starlette.dev/"class="external-link"target="_blank"><strong>Starlette</strong></a>. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi.
**FastAPI** est entièrement compatible avec (et basé sur) <ahref="https://www.starlette.dev/"class="external-link"target="_blank"><strong>Starlette</strong></a>. Donc, tout code Starlette additionnel que vous avez fonctionnera aussi.
En fait, `FastAPI` est un sous composant de `Starlette`. Donc, si vous savez déjà comment utiliser Starlette, la plupart des fonctionnalités fonctionneront de la même manière.
`FastAPI` est en fait une sous-classe de `Starlette`. Ainsi, si vous connaissez ou utilisez déjà Starlette, la plupart des fonctionnalités fonctionneront de la même manière.
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Starlette** (FastAPI est juste Starlette sous stéroïdes):
Avec **FastAPI** vous obtenez toutes les fonctionnalités de **Starlette** (puisque FastAPI est juste Starlette sous stéroïdes):
* Des performances vraiment impressionnantes. C'est l'<ahref="https://github.com/encode/starlette#performance"class="external-link"target="_blank">un des framework Python les plus rapide, à égalité avec **NodeJS** et **GO**</a>.
* Des performances vraiment impressionnantes. C'est <ahref="https://github.com/encode/starlette#performance"class="external-link"target="_blank">l’un des frameworks Python les plus rapides disponibles, à l’égal de **NodeJS** et **Go**</a>.
* Le support des **WebSockets**.
* Prise en charge des **WebSocket**.
* Le support de **GraphQL**.
* Tâches d'arrière-plan dans le processus.
* Les <abbrtitle="En anglais: In-process background tasks">tâches d'arrière-plan.</abbr>
* Évènements de démarrage et d'arrêt.
* Des évènements de démarrages et d'arrêt.
* Client de test basé sur HTTPX.
* Un client de test basé sur `request`
* **CORS**, GZip, fichiers statiques, réponses en streaming.
* 100 % de la base de code avec des annotations de type.
## Fonctionnalités de Pydantic
## Fonctionnalités de Pydantic { #pydantic-features }
**FastAPI** est totalement compatible avec (et basé sur) <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank"><strong>Pydantic</strong></a>. Le code utilisant Pydantic que vous ajouterez fonctionnera donc aussi.
**FastAPI** est entièrement compatible avec (et basé sur) <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank"><strong>Pydantic</strong></a>. Donc, tout code Pydantic additionnel que vous avez fonctionnera aussi.
Inclus des librairies externes basées, aussi, sur Pydantic, servent d'<abbrtitle="Object-Relational Mapper">ORM</abbr>s, <abbrtitle="Object-Document Mapper">ODM</abbr>s pour les bases de données.
Y compris des bibliothèques externes également basées sur Pydantic, servant d’<abbrtitle="Object-Relational Mapper - Mappeur objet-relationnel">ORM</abbr>, d’<abbrtitle="Object-Document Mapper - Mappeur objet-document">ODM</abbr> pour les bases de données.
Cela signifie aussi que, dans la plupart des cas, vous pouvez fournir l'objet reçu d'une requête **directement à la base de données**, comme tout est validé automatiquement.
Cela signifie également que, dans de nombreux cas, vous pouvez passer l'objet que vous recevez d'une requête **directement à la base de données**, puisque tout est validé automatiquement.
Inversement, dans la plupart des cas vous pourrez juste envoyer l'objet récupéré de la base de données **directement au client**
L’inverse est également vrai, dans de nombreux cas, vous pouvez simplement passer l'objet que vous récupérez de la base de données **directement au client**.
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Pydantic** (comme FastAPI est basé sur Pydantic pour toutes les manipulations de données):
Avec **FastAPI** vous obtenez toutes les fonctionnalités de **Pydantic** (puisque FastAPI est basé sur Pydantic pour toute la gestion des données) :
* **Pas de prise de tête**:
* **Pas de prise de tête**:
* Pas de nouveau langage de définition de schéma à apprendre.
* Pas de micro-langage de définition de schéma à apprendre.
* Si vous connaissez le typage en python vous savez comment utiliser Pydantic.
* Si vous connaissez les types Python vous savez utiliser Pydantic.
* Aide votre **<abbrtitle="Integrated Development Environment, il s'agit de votre éditeur de code">IDE</abbr>/<abbrtitle="Programme qui analyse le code à la recherche d'erreurs">linter</abbr>/cerveau**:
* Fonctionne bien avec votre **<abbrtitle="Integrated Development Environment - Environnement de développement intégré: similaire à un éditeur de code">IDE</abbr>/<dfntitle="Programme qui vérifie les erreurs de code">linter</dfn>/cerveau** :
* Parce que les structures de données de pydantic consistent seulement en une instance de classe que vous définissez; l'auto-complétion, le linting, mypy et votre intuition devrait être largement suffisante pour valider vos données.
* Parce que les structures de données de Pydantic sont simplement des instances de classes que vous définissez ; l'autocomplétion, le linting, mypy et votre intuition devraient tous bien fonctionner avec vos données validées.
* Valide les **structures complexes**:
* Valider des **structures complexes**:
* Utilise les modèles hiérarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc.
* Utilisation de modèles Pydantic hiérarchiques, de `List` et `Dict` du `typing` Python, etc.
* Et les validateurs permettent aux schémas de données complexes d'être clairement et facilement définis, validés et documentés sous forme d'un schéma JSON.
* Et les validateurs permettent de définir, vérifier et documenter clairement et facilement des schémas de données complexes en tant que JSON Schema.
* Vous pouvez avoir des objets **JSON fortement imbriqués** tout en ayant, pour chacun, de la validation et des annotations.
* Vous pouvez avoir des objets **JSON fortement imbriqués** et les faire tous valider et annoter.
* **Renouvelable**:
* **Extensible**:
* Pydantic permet de définir de nouveaux types de données ou vous pouvez étendre la validation avec des méthodes sur un modèle décoré avec le<abbrtitle="en anglais: validator decorator"> décorateur de validation</abbr>
* Pydantic permet de définir des types de données personnalisés ou vous pouvez étendre la validation avec des méthodes sur un modèle décoré avec le décorateur de validation.
# Aider FastAPI - Obtenir de l'aide { #help-fastapi-get-help }
Aimez-vous **FastAPI** ?
Aimez-vous **FastAPI** ?
Vous souhaitez aider FastAPI, les autres utilisateurs et l'auteur ?
Souhaitez-vous aider FastAPI, les autres utilisateurs et l'auteur ?
Ou souhaitez-vous obtenir de l'aide avec le **FastAPI** ?
Ou souhaitez-vous obtenir de l'aide avec **FastAPI** ?
Il existe des moyens très simples d'aider (plusieurs ne nécessitent qu'un ou deux clics).
Il existe des moyens très simples d'aider (plusieurs ne nécessitent qu'un ou deux clics).
Il existe également plusieurs façons d'obtenir de l'aide.
Et il existe aussi plusieurs façons d'obtenir de l'aide.
## Star **FastAPI** sur GitHub
## S'abonner à la newsletter { #subscribe-to-the-newsletter }
Vous pouvez "star" FastAPI dans GitHub (en cliquant sur le bouton étoile en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
Vous pouvez vous abonner à la (peu fréquente) [newsletter **FastAPI and friends**](newsletter.md){.internal-link target=_blank} pour rester informé à propos :
En ajoutant une étoile, les autres utilisateurs pourront la trouver plus facilement et constater qu'elle a déjà été utile à d'autres.
* Nouvelles sur FastAPI et ses amis 🚀
* Guides 📝
* Fonctionnalités ✨
* Changements majeurs 🚨
* Astuces et conseils ✅
## Watch le dépôt GitHub pour les releases
## Suivre FastAPI sur X (Twitter) { #follow-fastapi-on-x-twitter }
Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. 👀
<ahref="https://x.com/fastapi"class="external-link"target="_blank">Suivez @fastapi sur **X (Twitter)**</a> pour obtenir les dernières nouvelles sur **FastAPI**. 🐦
Vous pouvez y sélectionner "Releases only".
## Mettre une étoile à **FastAPI** sur GitHub { #star-fastapi-in-github }
Ainsi, vous recevrez des notifications (dans votre courrier électronique) chaque fois qu'il y aura une nouvelle version de **FastAPI** avec des corrections de bugs et de nouvelles fonctionnalités.
Vous pouvez « star » FastAPI sur GitHub (en cliquant sur le bouton étoile en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
## Se rapprocher de l'auteur
En ajoutant une étoile, les autres utilisateurs pourront le trouver plus facilement et voir qu'il a déjà été utile à d'autres.
## Suivre le dépôt GitHub pour les releases { #watch-the-github-repository-for-releases }
Vous pouvez :
Vous pouvez « watch » FastAPI sur GitHub (en cliquant sur le bouton « watch » en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Vous pouvez y sélectionner « Releases only ».
Ainsi, vous recevrez des notifications (par e‑mail) chaque fois qu'il y aura une nouvelle release (une nouvelle version) de **FastAPI** avec des corrections de bugs et de nouvelles fonctionnalités.
## Entrer en contact avec l'auteur { #connect-with-the-author }
Vous pouvez entrer en contact avec <ahref="https://tiangolo.com"class="external-link"target="_blank">moi (Sebastián Ramírez / `tiangolo`)</a>, l'auteur.
Vous pouvez :
* <ahref="https://github.com/tiangolo"class="external-link"target="_blank">Me suivre sur **GitHub**</a>.
* <ahref="https://github.com/tiangolo"class="external-link"target="_blank">Me suivre sur **GitHub**</a>.
* Voir d'autres projets Open Source que j'ai créés et qui pourraient vous aider.
* Voir d'autres projets Open Source que j'ai créés et qui pourraient vous aider.
* Suivez-moi pour voir quand je crée un nouveau projet Open Source.
* Me suivre pour voir quand je crée un nouveau projet Open Source.
* <ahref="https://x.com/tiangolo"class="external-link"target="_blank">Me suivre sur **X (Twitter)**</a>.
* <ahref="https://x.com/tiangolo"class="external-link"target="_blank">Me suivre sur **X (Twitter)**</a> ou sur <ahref="https://fosstodon.org/@tiangolo"class="external-link"target="_blank">Mastodon</a>.
* Me dire comment vous utilisez FastAPI (j'adore l'entendre).
* Entendre quand je fais des annonces ou que je lance de nouveaux outils.
* Être informé quand je fais des annonces ou publie de nouveaux outils.
* <ahref="https://www.linkedin.com/in/tiangolo/"class="external-link"target="_blank">Vous connectez à moi sur **LinkedIn**</a>.
* Vous pouvez aussi <ahref="https://x.com/fastapi"class="external-link"target="_blank">suivre @fastapi sur X (Twitter)</a> (un compte séparé).
* Etre notifié quand je fais des annonces ou que je lance de nouveaux outils (bien que j'utilise plus souvent X (Twitter) 🤷♂).
* <ahref="https://www.linkedin.com/in/tiangolo/"class="external-link"target="_blank">Me suivre sur **LinkedIn**</a>.
* Lire ce que j’écris (ou me suivre) sur <ahref="https://dev.to/tiangolo"class="external-link"target="_blank">**Dev.to**</a> ou <ahref="https://medium.com/@tiangolo"class="external-link"target="_blank">**Medium**</a>.
* Être informé quand je fais des annonces ou publie de nouveaux outils (même si j'utilise plus souvent X (Twitter) 🤷♂).
* Lire d'autres idées, articles, et sur les outils que j'ai créés.
* Lire ce que j'écris (ou me suivre) sur <ahref="https://dev.to/tiangolo"class="external-link"target="_blank">**Dev.to**</a> ou <ahref="https://medium.com/@tiangolo"class="external-link"target="_blank">**Medium**</a>.
* Suivez-moi pour lire quand je publie quelque chose de nouveau.
* Lire d'autres idées, des articles, et découvrir des outils que j'ai créés.
* Me suivre pour lire quand je publie quelque chose de nouveau.
## Tweeter sur **FastAPI**
## Tweeter à propos de **FastAPI** { #tweet-about-fastapi }
<ahref="https://x.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/fastapi/fastapi cc @tiangolo"class="external-link"target="_blank">Tweetez à propos de **FastAPI**</a> et faites-moi savoir, ainsi qu'aux autres, pourquoi vous aimez ça. 🎉
<ahref="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi"class="external-link"target="_blank">Tweetez à propos de **FastAPI**</a> et faites savoir à moi et aux autres pourquoi vous l'appréciez. 🎉
J'aime entendre parler de l'utilisation du **FastAPI**, de ce que vous avez aimé dedans, dans quel projet/entreprise l'utilisez-vous, etc.
J'adore entendre comment **FastAPI** est utilisé, ce que vous avez aimé, dans quel projet/quelle entreprise vous l'utilisez, etc.
## Voter pour FastAPI
## Voter pour FastAPI { #vote-for-fastapi }
* <ahref="https://www.slant.co/options/34241/~fastapi-review"class="external-link"target="_blank">Votez pour **FastAPI** sur Slant</a>.
* <ahref="https://www.slant.co/options/34241/~fastapi-review"class="external-link"target="_blank">Votez pour **FastAPI** sur Slant</a>.
* <ahref="https://alternativeto.net/software/fastapi/"class="external-link"target="_blank">Votez pour **FastAPI** sur AlternativeTo</a>.
* <ahref="https://alternativeto.net/software/fastapi/about/"class="external-link"target="_blank">Votez pour **FastAPI** sur AlternativeTo</a>.
* <ahref="https://github.com/marmelab/awesome-rest/pull/93"class="external-link"target="_blank">Votez pour **FastAPI** sur awesome-rest</a>.
* <ahref="https://stackshare.io/pypi-fastapi"class="external-link"target="_blank">Indiquez que vous utilisez **FastAPI** sur StackShare</a>.
## Aider les autres avec des questions sur GitHub { #help-others-with-questions-in-github }
Vous pouvez essayer d'aider les autres avec leurs questions dans :
Dans de nombreux cas, vous connaissez peut-être déjà la réponse à ces questions. 🤓
Si vous aidez beaucoup de personnes avec leurs questions, vous deviendrez un [Expert FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank} officiel. 🎉
N'oubliez pas, le point le plus important est : essayez d'être aimable. Les gens viennent avec leurs frustrations et, dans bien des cas, ne posent pas la question de la meilleure façon, mais faites de votre mieux pour rester aimable. 🤗
L'idée est que la communauté **FastAPI** soit bienveillante et accueillante. En même temps, n'acceptez pas l'intimidation ni les comportements irrespectueux envers les autres. Nous devons prendre soin les uns des autres.
---
Voici comment aider les autres avec des questions (dans les discussions ou les issues) :
### Comprendre la question { #understand-the-question }
* Vérifiez si vous comprenez quel est l’**objectif** et le cas d'utilisation de la personne qui pose la question.
* Ensuite, vérifiez si la question (la grande majorité sont des questions) est **claire**.
## Aider les autres à résoudre les problèmes dans GitHub
* Dans de nombreux cas, la question porte sur une solution imaginaire de l'utilisateur, mais il pourrait y en avoir une **meilleure**. Si vous comprenez mieux le problème et le cas d'utilisation, vous pourriez suggérer une **solution alternative** plus adaptée.
Vous pouvez voir <ahref="https://github.com/fastapi/fastapi/issues"class="external-link"target="_blank">les problèmes existants</a> et essayer d'aider les autres, la plupart du temps il s'agit de questions dont vous connaissez peut-être déjà la réponse. 🤓
* Si vous ne comprenez pas la question, demandez plus de **détails**.
## Watch le dépôt GitHub
### Reproduire le problème { #reproduce-the-problem }
Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Dans la plupart des cas et pour la plupart des questions, il y a quelque chose lié au **code original** de la personne.
Si vous sélectionnez "Watching" au lieu de "Releases only", vous recevrez des notifications lorsque quelqu'un crée une nouvelle Issue.
Dans de nombreux cas, elle ne copiera qu'un fragment de code, mais ce n'est pas suffisant pour **reproduire le problème**.
Vous pouvez alors essayer de les aider à résoudre ces problèmes.
* Vous pouvez leur demander de fournir un <ahref="https://stackoverflow.com/help/minimal-reproducible-example"class="external-link"target="_blank">exemple minimal, complet et vérifiable</a>, que vous pouvez **copier‑coller** et exécuter localement pour voir la même erreur ou le même comportement qu'ils observent, ou pour mieux comprendre leur cas d'utilisation.
## Créer une Issue
* Si vous vous sentez très généreux, vous pouvez essayer de **créer un tel exemple** vous‑même, simplement à partir de la description du problème. Gardez simplement à l'esprit que cela peut prendre beaucoup de temps et qu'il peut être préférable de leur demander d'abord de clarifier le problème.
Vous pouvez <ahref="https://github.com/fastapi/fastapi/issues/new/choose"class="external-link"target="_blank">créer une Issue</a> dans le dépôt GitHub, par exemple pour :
### Suggérer des solutions { #suggest-solutions }
* Poser une question ou s'informer sur un problème.
* Après avoir compris la question, vous pouvez leur donner une **réponse** possible.
* Suggérer une nouvelle fonctionnalité.
* Dans de nombreux cas, il est préférable de comprendre leur **problème sous‑jacent ou cas d'utilisation**, car il pourrait exister une meilleure façon de le résoudre que ce qu'ils essaient de faire.
### Demander la clôture { #ask-to-close }
S'ils répondent, il y a de fortes chances que vous ayez résolu leur problème, bravo, **vous êtes un héros** ! 🦸
* Maintenant, si cela a résolu leur problème, vous pouvez leur demander de :
* Dans GitHub Discussions : marquer le commentaire comme **réponse**.
* Dans GitHub Issues : **fermer** l'issue.
## Suivre le dépôt GitHub { #watch-the-github-repository }
Vous pouvez « watch » FastAPI sur GitHub (en cliquant sur le bouton « watch » en haut à droite) : <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Si vous sélectionnez « Watching » au lieu de « Releases only », vous recevrez des notifications lorsque quelqu'un crée une nouvelle issue ou question. Vous pouvez aussi préciser que vous ne souhaitez être notifié que pour les nouvelles issues, ou les discussions, ou les PR, etc.
Vous pouvez alors essayer de les aider à résoudre ces questions.
## Poser des questions { #ask-questions }
Vous pouvez <ahref="https://github.com/fastapi/fastapi/discussions/new?category=questions"class="external-link"target="_blank">créer une nouvelle question</a> dans le dépôt GitHub, par exemple pour :
* Poser une **question** ou demander à propos d'un **problème**.
* Suggérer une nouvelle **fonctionnalité**.
**Remarque** : si vous le faites, je vais vous demander d'aider aussi les autres. 😉
## Relire des Pull Requests { #review-pull-requests }
Vous pouvez m'aider à relire les pull requests des autres.
Encore une fois, essayez autant que possible d'être aimable. 🤗
---
**Note** : si vous créez un problème, alors je vais vous demander d'aider aussi les autres. 😉
Voici ce à garder à l'esprit et comment relire une pull request :
## Créer une Pull Request
### Comprendre le problème { #understand-the-problem }
Vous pouvez <ahref="https://github.com/fastapi/fastapi"class="external-link"target="_blank">créer une Pull Request</a>, par exemple :
* D'abord, assurez‑vous de **comprendre le problème** que la pull request essaie de résoudre. Il peut y avoir une discussion plus longue dans une GitHub Discussion ou une issue.
* Pour corriger une faute de frappe que vous avez trouvée sur la documentation.
* Il y a aussi de bonnes chances que la pull request ne soit pas réellement nécessaire parce que le problème peut être résolu d'une **autre manière**. Vous pouvez alors le suggérer ou poser la question.
### Ne pas s'inquiéter du style { #dont-worry-about-style }
* Ne vous souciez pas trop des choses comme les styles de messages de commit, je ferai un squash and merge en personnalisant le commit manuellement.
* Ne vous inquiétez pas non plus des règles de style, il existe déjà des outils automatisés qui vérifient cela.
Et s'il y a d'autres besoins de style ou de cohérence, je le demanderai directement, ou j'ajouterai des commits par‑dessus avec les changements nécessaires.
### Vérifier le code { #check-the-code }
* Vérifiez et lisez le code, voyez s'il a du sens, **exécutez‑le localement** et voyez s'il résout effectivement le problème.
* Ensuite, **commentez** en disant que vous l'avez fait, c'est ainsi que je saurai que vous l'avez vraiment vérifié.
/// info
Malheureusement, je ne peux pas simplement faire confiance aux PR qui ont juste plusieurs approbations.
Plusieurs fois, il est arrivé qu'il y ait des PR avec 3, 5 ou plus approbations, probablement parce que la description est attrayante, mais lorsque je vérifie les PR, elles sont en fait cassées, ont un bug, ou ne résolvent pas le problème qu'elles prétendent résoudre. 😅
Donc, il est vraiment important que vous lisiez et exécutiez le code, et que vous me le disiez dans les commentaires. 🤓
///
* Si la PR peut être simplifiée d'une certaine manière, vous pouvez le demander, mais il n'est pas nécessaire d'être trop pointilleux, il peut y avoir beaucoup de points de vue subjectifs (et j'aurai les miens aussi 🙈), donc il est préférable de vous concentrer sur les choses fondamentales.
### Tests { #tests }
* Aidez‑moi à vérifier que la PR a des **tests**.
* Vérifiez que les tests **échouent** avant la PR. 🚨
* Puis vérifiez que les tests **réussissent** après la PR. ✅
* Beaucoup de PR n'ont pas de tests, vous pouvez leur **rappeler** d'ajouter des tests, ou même **suggérer** des tests vous‑même. C'est l'une des choses qui consomment le plus de temps et vous pouvez beaucoup aider.
* Commentez aussi ce que vous avez essayé, ainsi je saurai que vous l'avez vérifié. 🤓
## Créer une Pull Request { #create-a-pull-request }
Vous pouvez [contribuer](contributing.md){.internal-link target=_blank} au code source avec des Pull Requests, par exemple :
* Corriger une coquille que vous avez trouvée dans la documentation.
* Partager un article, une vidéo ou un podcast que vous avez créé ou trouvé à propos de FastAPI en <ahref="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml"class="external-link"target="_blank">modifiant ce fichier</a>.
* Vous devez vous assurer d'ajouter votre lien au début de la section correspondante.
* Aider à [traduire la documentation](contributing.md#translations){.internal-link target=_blank} dans votre langue.
* Vous pouvez aussi aider à relire les traductions créées par d'autres.
* Proposer de nouvelles sections de documentation.
* Proposer de nouvelles sections de documentation.
* Pour corriger une Issue/Bug existant.
* Corriger une issue/un bug existant.
* Pour ajouter une nouvelle fonctionnalité.
* Vous devez ajouter des tests.
* Ajouter une nouvelle fonctionnalité.
* Vous devez ajouter des tests.
* Vous devez ajouter de la documentation si c'est pertinent.
## Aider à maintenir FastAPI { #help-maintain-fastapi }
Aidez‑moi à maintenir **FastAPI** ! 🤓
Il y a beaucoup de travail à faire, et pour la plupart, **VOUS** pouvez le faire.
Les principales tâches que vous pouvez faire dès maintenant sont :
* [Aider les autres avec des questions sur GitHub](#help-others-with-questions-in-github){.internal-link target=_blank} (voir la section ci‑dessus).
* [Relire des Pull Requests](#review-pull-requests){.internal-link target=_blank} (voir la section ci‑dessus).
Ces deux tâches sont celles qui **consomment le plus de temps**. C'est le travail principal de la maintenance de FastAPI.
Si vous pouvez m'aider avec cela, **vous m'aidez à maintenir FastAPI** et à vous assurer qu'il continue **d'avancer plus vite et mieux**. 🚀
## Rejoindre le chat { #join-the-chat }
Rejoignez le 👥 <ahref="https://discord.gg/VQjSZaeJmf"class="external-link"target="_blank">serveur Discord</a> 👥 et échangez avec d'autres membres de la communauté FastAPI.
/// tip | Astuce
Pour les questions, posez‑les dans <ahref="https://github.com/fastapi/fastapi/discussions/new?category=questions"class="external-link"target="_blank">GitHub Discussions</a>, vous avez bien plus de chances de recevoir de l'aide par les [Experts FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}.
Utilisez le chat uniquement pour d'autres conversations générales.
///
## Parrainer l'auteur
### N'utilisez pas le chat pour les questions { #dont-use-the-chat-for-questions }
Vous pouvez également soutenir financièrement l'auteur (moi) via <ahref="https://github.com/sponsors/tiangolo"class="external-link"target="_blank">GitHub sponsors</a>.
Gardez à l'esprit que, comme les chats permettent une « conversation libre », il est facile de poser des questions trop générales et plus difficiles à répondre ; vous pourriez donc ne pas recevoir de réponses.
Là, vous pourriez m'offrir un café ☕️ pour me remercier 😄.
Sur GitHub, le modèle vous guidera pour rédiger la bonne question afin que vous puissiez plus facilement obtenir une bonne réponse, ou même résoudre le problème vous‑même avant de demander. Et sur GitHub, je peux m'assurer de toujours tout répondre, même si cela prend du temps. Je ne peux pas personnellement faire cela avec les systèmes de chat. 😅
## Sponsoriser les outils qui font fonctionner FastAPI
Les conversations dans les systèmes de chat ne sont pas non plus aussi facilement recherchables que sur GitHub, donc les questions et réponses peuvent se perdre dans la conversation. Et seules celles sur GitHub comptent pour devenir un [Expert FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, vous aurez donc très probablement plus d'attention sur GitHub.
Comme vous l'avez vu dans la documentation, FastAPI se tient sur les épaules des géants, Starlette et Pydantic.
D'un autre côté, il y a des milliers d'utilisateurs dans les systèmes de chat, il y a donc de fortes chances que vous trouviez presque toujours quelqu'un avec qui parler. 😄
Si votre **produit/entreprise** dépend de **FastAPI** ou y est lié et que vous souhaitez atteindre ses utilisateurs, vous pouvez sponsoriser l'auteur (moi) via <ahref="https://github.com/sponsors/tiangolo"class="external-link"target="_blank">GitHub sponsors</a>. Selon le niveau, vous pourriez obtenir des avantages supplémentaires, comme un badge dans la documentation. 🎁
# Histoire, conception et avenir { #history-design-and-future }
Il y a quelque temps, <ahref="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920"class="external-link"target="_blank">un utilisateur de **FastAPI** a demandé</a> :
Il y a quelque temps, <ahref="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920"class="external-link"target="_blank">un utilisateur de **FastAPI** a demandé</a> :
@ -6,7 +6,7 @@ Il y a quelque temps, <a href="https://github.com/fastapi/fastapi/issues/3#issue
Voici un petit bout de cette histoire.
Voici un petit bout de cette histoire.
## Alternatives
## Alternatives { #alternatives }
Je crée des API avec des exigences complexes depuis plusieurs années (Machine Learning, systèmes distribués, jobs asynchrones, bases de données NoSQL, etc), en dirigeant plusieurs équipes de développeurs.
Je crée des API avec des exigences complexes depuis plusieurs années (Machine Learning, systèmes distribués, jobs asynchrones, bases de données NoSQL, etc), en dirigeant plusieurs équipes de développeurs.
@ -28,7 +28,7 @@ Mais à un moment donné, il n'y avait pas d'autre option que de créer quelque
</blockquote>
</blockquote>
## Recherche
## Recherche { #investigation }
En utilisant toutes les alternatives précédentes, j'ai eu la chance d'apprendre de toutes, de prendre des idées, et de les combiner de la meilleure façon que j'ai pu trouver pour moi-même et les équipes de développeurs avec lesquelles j'ai travaillé.
En utilisant toutes les alternatives précédentes, j'ai eu la chance d'apprendre de toutes, de prendre des idées, et de les combiner de la meilleure façon que j'ai pu trouver pour moi-même et les équipes de développeurs avec lesquelles j'ai travaillé.
@ -38,9 +38,9 @@ De plus, la meilleure approche était d'utiliser des normes déjà existantes.
Ainsi, avant même de commencer à coder **FastAPI**, j'ai passé plusieurs mois à étudier les spécifications d'OpenAPI, JSON Schema, OAuth2, etc. Comprendre leurs relations, leurs similarités et leurs différences.
Ainsi, avant même de commencer à coder **FastAPI**, j'ai passé plusieurs mois à étudier les spécifications d'OpenAPI, JSON Schema, OAuth2, etc. Comprendre leurs relations, leurs similarités et leurs différences.
## Conception
## Conception { #design }
Ensuite, j'ai passé du temps à concevoir l'"API" de développeur que je voulais avoir en tant qu'utilisateur (en tant que développeur utilisant FastAPI).
Ensuite, j'ai passé du temps à concevoir l'« API » de développeur que je voulais avoir en tant qu'utilisateur (en tant que développeur utilisant FastAPI).
J'ai testé plusieurs idées dans les éditeurs Python les plus populaires : PyCharm, VS Code, les éditeurs basés sur Jedi.
J'ai testé plusieurs idées dans les éditeurs Python les plus populaires : PyCharm, VS Code, les éditeurs basés sur Jedi.
@ -48,11 +48,11 @@ D'après la dernière <a href="https://www.jetbrains.com/research/python-develop
Cela signifie que **FastAPI** a été spécifiquement testé avec les éditeurs utilisés par 80% des développeurs Python. Et comme la plupart des autres éditeurs ont tendance à fonctionner de façon similaire, tous ses avantages devraient fonctionner pour pratiquement tous les éditeurs.
Cela signifie que **FastAPI** a été spécifiquement testé avec les éditeurs utilisés par 80% des développeurs Python. Et comme la plupart des autres éditeurs ont tendance à fonctionner de façon similaire, tous ses avantages devraient fonctionner pour pratiquement tous les éditeurs.
Ainsi, j'ai pu trouver les meilleurs moyens de réduire autant que possible la duplication du code, d'avoir la complétion partout, les contrôles de type et d'erreur, etc.
Ainsi, j'ai pu trouver les meilleurs moyens de réduire autant que possible la duplication du code, d'avoir l'autocomplétion partout, les contrôles de type et d'erreur, etc.
Le tout de manière à offrir la meilleure expérience de développement à tous les développeurs.
Le tout de manière à offrir la meilleure expérience de développement à tous les développeurs.
## Exigences
## Exigences { #requirements }
Après avoir testé plusieurs alternatives, j'ai décidé que j'allais utiliser <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank">**Pydantic**</a> pour ses avantages.
Après avoir testé plusieurs alternatives, j'ai décidé que j'allais utiliser <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank">**Pydantic**</a> pour ses avantages.
@ -60,11 +60,11 @@ J'y ai ensuite contribué, pour le rendre entièrement compatible avec JSON Sche
Pendant le développement, j'ai également contribué à <ahref="https://www.starlette.dev/"class="external-link"target="_blank">**Starlette**</a>, l'autre exigence clé.
Pendant le développement, j'ai également contribué à <ahref="https://www.starlette.dev/"class="external-link"target="_blank">**Starlette**</a>, l'autre exigence clé.
## Développement
## Développement { #development }
Au moment où j'ai commencé à créer **FastAPI** lui-même, la plupart des pièces étaient déjà en place, la conception était définie, les exigences et les outils étaient prêts, et la connaissance des normes et des spécifications était claire et fraîche.
Au moment où j'ai commencé à créer **FastAPI** lui-même, la plupart des pièces étaient déjà en place, la conception était définie, les exigences et les outils étaient prêts, et la connaissance des normes et des spécifications était claire et fraîche.
## Futur
## Futur { #future }
À ce stade, il est déjà clair que **FastAPI** et ses idées sont utiles pour de nombreuses personnes.
À ce stade, il est déjà clair que **FastAPI** et ses idées sont utiles pour de nombreuses personnes.
@ -40,7 +40,7 @@ Les principales fonctionnalités sont :
* **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** : 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 %. *
* **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. *
* **Moins de bugs** : réduit d'environ 40 % les erreurs induites par le développeur. *
* **Intuitif** : excellente compatibilité avec les éditeurs. <abbrtitle="également appelé autocomplétion, IntelliSense">Autocomplétion</abbr> partout. Moins de temps passé à déboguer.
* **Intuitif** : excellente compatibilité avec les éditeurs. <dfntitle="également connu sous le nom de : auto-complétion, autocomplétion, IntelliSense">Autocomplétion</dfn> partout. Moins de temps passé à déboguer.
* **Facile** : conçu pour être facile à utiliser et à apprendre. Moins de temps passé à lire les documents.
* **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.
* **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.
* **Robuste** : obtenez un code prêt pour la production. Avec une documentation interactive automatique.
@ -368,7 +368,7 @@ item: Item
* La validation des données :
* La validation des données :
* des erreurs automatiques et claires lorsque les données ne sont pas valides.
* des erreurs automatiques et claires lorsque les données ne sont pas valides.
* une validation même pour les objets JSON profondément imbriqués.
* une validation même pour les objets JSON profondément imbriqués.
* <abbrtitle="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 :
* <dfntitle="également connu sous le nom de : sérialisation, parsing, marshalling">Conversion</dfn> des données d'entrée : venant du réseau vers les données et types Python. Lecture depuis :
* JSON.
* JSON.
* Paramètres de chemin.
* Paramètres de chemin.
* Paramètres de requête.
* Paramètres de requête.
@ -376,7 +376,7 @@ item: Item
* En-têtes.
* En-têtes.
* Formulaires.
* Formulaires.
* Fichiers.
* Fichiers.
* <abbrtitle="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) :
* <dfntitle="également connu sous le nom de : sérialisation, parsing, marshalling">Conversion</dfn> des données de sortie : conversion des données et types Python en données réseau (au format JSON) :
@ -439,7 +439,7 @@ Pour un exemple plus complet comprenant plus de fonctionnalités, voir le <a hre
* Déclaration de **paramètres** provenant d'autres emplacements comme : **en-têtes**, **cookies**, **champs de formulaire** et **fichiers**.
* 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`.
* Comment définir des **contraintes de validation** comme `maximum_length` ou `regex`.
* Un système **<abbrtitle="aussi connu sous le nom de composants, ressources, fournisseurs, services, injectables">d'injection de dépendances</abbr>** très puissant et facile à utiliser.
* Un système **<dfntitle="également connu sous le nom de : composants, ressources, fournisseurs, services, injectables">d'injection de dépendances</dfn>** 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**.
* 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).
* 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 <ahref="https://strawberry.rocks"class="external-link"target="_blank">Strawberry</a> et d'autres bibliothèques.
* Intégration **GraphQL** avec <ahref="https://strawberry.rocks"class="external-link"target="_blank">Strawberry</a> et d'autres bibliothèques.
@ -524,7 +524,7 @@ Utilisées par Starlette :
* <ahref="https://www.python-httpx.org"target="_blank"><code>httpx</code></a> - Obligatoire si vous souhaitez utiliser le `TestClient`.
* <ahref="https://www.python-httpx.org"target="_blank"><code>httpx</code></a> - Obligatoire si vous souhaitez utiliser le `TestClient`.
* <ahref="https://jinja.palletsprojects.com"target="_blank"><code>jinja2</code></a> - Obligatoire si vous souhaitez utiliser la configuration de template par défaut.
* <ahref="https://jinja.palletsprojects.com"target="_blank"><code>jinja2</code></a> - Obligatoire si vous souhaitez utiliser la configuration de template par défaut.
* <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - Obligatoire si vous souhaitez prendre en charge l’<abbrtitle="convertir la chaîne issue d'une requête HTTP en données Python">« parsing »</abbr> de formulaires avec `request.form()`.
* <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - Obligatoire si vous souhaitez prendre en charge l’<dfntitle="convertir la chaîne issue d'une requête HTTP en données Python">« parsing »</dfn> de formulaires avec `request.form()`.
# Introduction aux types Python { #python-types-intro }
# Introduction aux types Python { #python-types-intro }
Python prend en charge des « type hints » (aussi appelées « annotations de type ») facultatives.
Python prend en charge des « annotations de type » (aussi appelées « type hints ») facultatives.
Ces « type hints » ou annotations sont une syntaxe spéciale qui permet de déclarer le <abbrtitle="par exemple : str, int, float, bool">type</abbr> d'une variable.
Ces **« annotations de type »** sont une syntaxe spéciale qui permet de déclarer le <dfntitle="par exemple : str, int, float, bool">type</dfn> d'une variable.
En déclarant les types de vos variables, les éditeurs et outils peuvent vous offrir un meilleur support.
En déclarant les types de vos variables, les éditeurs et outils peuvent vous offrir un meilleur support.
@ -22,7 +22,7 @@ Si vous êtes un expert Python, et que vous savez déjà tout sur les annotation
### Types génériques avec paramètres de type { #generic-types-with-type-parameters }
### Module `typing` { #typing-module }
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 certains cas d'utilisation supplémentaires, vous pourriez avoir besoin d'importer certains éléments depuis le module standard `typing`, par exemple lorsque vous voulez déclarer que quelque chose a « n'importe quel type », vous pouvez utiliser `Any` depuis `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.
```python
from typing import Any
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.
#### Versions plus récentes de Python { #newer-versions-of-python }
def some_function(data: Any):
print(data)
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.
```
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.
### Types génériques { #generic-types }
Si vous pouvez choisir une version plus récente de Python pour votre projet, vous pourrez profiter de cette simplicité supplémentaire.
Certains types peuvent prendre des « paramètres de type » entre crochets, pour définir leurs types internes, par exemple une « liste de chaînes » se déclarerait `list[str]`.
Dans toute la documentation, il y a des exemples compatibles avec chaque version de Python (lorsqu'il y a une différence).
Ces types qui peuvent prendre des paramètres de type sont appelés des **types génériques** ou **Generics**.
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).
Vous pouvez utiliser les mêmes types intégrés comme génériques (avec des crochets et des types à l'intérieur) :
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+ ».
* `list`
* `tuple`
* `set`
* `dict`
#### Liste { #list }
#### Liste { #list }
@ -167,9 +170,9 @@ Comme type, mettez `list`.
Comme la liste est un type qui contient des types internes, mettez-les entre crochets :
Comme la liste est un type qui contient des types internes, mettez-les entre crochets :
Vous pouvez déclarer qu'une variable peut être de plusieurs types, par exemple, un `int` ou un `str`.
Vous pouvez déclarer qu'une variable peut être **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 <abbrtitle='aussi appelé « opérateur OU bit à bit », mais ce sens n’est pas pertinent ici'>barre verticale (`|`)</abbr>.
Pour le définir, vous utilisez la <dfntitle='aussi appelé « opérateur OU bit à bit », mais ce sens n’est pas pertinent ici'>barre verticale (`|`)</dfn> pour séparer les deux types.
//// tab | Python 3.10+
C'est ce qu'on appelle une « union », car la variable peut être n'importe quoi dans l'union de ces deux ensembles de types.
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+
//// tab | Python 3.10+
```Python hl_lines="1"
```Python hl_lines="1"
@ -266,96 +245,7 @@ Cela signifie aussi que dans Python 3.10, vous pouvez utiliser `Something | None
////
////
//// tab | Python 3.9+
Utiliser `str | None` 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`.
#### 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.
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 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 :
```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 🎉
```
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 :
Et alors vous n'aurez plus à vous soucier de noms comme `Optional` et `Union`. 😎
#### Types génériques { #generic-types }
Ces types qui prennent des paramètres de type entre crochets sont appelés des **types génériques** ou **Generics**, par exemple :
//// tab | Python 3.10+
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.
Dans Python 3.10, comme alternative à l'utilisation des génériques `Union` et `Optional`, vous pouvez utiliser la <abbrtitle='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.
////
//// 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 }
### Classes en tant que types { #classes-as-types }
@ -363,19 +253,19 @@ Vous pouvez aussi déclarer une classe comme type d'une variable.
Disons que vous avez une classe `Person`, avec un nom :
Disons que vous avez une classe `Person`, avec un nom :
Pour en savoir plus à propos de <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank">Pydantic, consultez sa documentation</a>.
Pour en savoir plus à propos de <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank">Pydantic, consultez sa documentation</a>.
@ -403,33 +293,27 @@ Pour en savoir plus à propos de <a href="https://docs.pydantic.dev/" class="ext
Vous verrez beaucoup plus de tout cela en pratique dans le [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
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 <ahref="https://docs.pydantic.dev/2.3/usage/models/#required-fields"class="external-link"target="_blank">champs Optionals requis</a>.
///
## Annotations de type avec métadonnées { #type-hints-with-metadata-annotations }
## Annotations de type avec métadonnées { #type-hints-with-metadata-annotations }
Python dispose également d'une fonctionnalité qui permet de mettre des **<abbrtitle="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`.
Python dispose également d'une fonctionnalité qui permet de mettre des **<dfntitle="Données sur les données, dans ce cas, des informations sur le type, p. ex. une description.">métadonnées</dfn> 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`.
Python lui-même ne fait rien avec ce `Annotated`. Et pour les éditeurs et autres outils, le type est toujours `str`.
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.
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.
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. 😎
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.
Plus tard, vous verrez à quel point cela peut être **puissant**.
/// tip | Astuce
/// 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. ✨
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. 🚀
Et aussi que votre code sera très compatible avec de nombreux autres outils et bibliothèques Python. 🚀
@ -457,7 +341,7 @@ Tout cela peut sembler abstrait. Ne vous inquiétez pas. Vous verrez tout cela e
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.
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
/// info | Info
Si vous avez déjà parcouru tout le tutoriel et êtes revenu pour en voir plus sur les types, une bonne ressource est <ahref="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html"class="external-link"target="_blank">l'« aide-mémoire » 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 <ahref="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html"class="external-link"target="_blank">l'« aide-mémoire » de `mypy`</a>.
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 d'accès* avec `BackgroundTasks` comme type déclaré.
## Ajouter une tâche d'arrière-plan { #add-the-background-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()` :
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()` :
@ -10,7 +10,7 @@ Pour déclarer un corps de **requête**, on utilise les modèles de <a href="htt
/// info
/// info
Pour envoyer de la donnée, vous devriez utiliser : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`.
Pour envoyer de la donnée, vous devez utiliser : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`.
Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par **FastAPI**, seulement pour des cas d'utilisation très complexes/extrêmes.
Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par **FastAPI**, seulement pour des cas d'utilisation très complexes/extrêmes.
@ -56,7 +56,7 @@ Par exemple, le modèle ci-dessus déclare un JSON « `object` » (ou `dict` P
## Le déclarer comme paramètre { #declare-it-as-a-parameter }
## 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 :
Pour l'ajouter à votre *chemin d'accès*, déclarez-le comme vous déclareriez des paramètres de chemin ou de requête :
@ -81,7 +81,7 @@ Les schémas JSON de vos modèles seront intégrés au schéma OpenAPI global de
<imgsrc="/img/tutorial/body/image01.png">
<imgsrc="/img/tutorial/body/image01.png">
Et seront aussi utilisés dans chaque *opération de chemin* de la documentation utilisant ces modèles :
Et seront aussi utilisés dans chaque *chemin d'accès* de la documentation utilisant ces modèles :
<imgsrc="/img/tutorial/body/image02.png">
<imgsrc="/img/tutorial/body/image02.png">
@ -115,7 +115,7 @@ Ce qui améliore le support pour les modèles Pydantic avec :
* de l'autocomplétion
* de l'autocomplétion
* des vérifications de type
* des vérifications de type
* du « refactoring » (ou remaniement de code)
* du « refactoring »
* de la recherche
* de la recherche
* des inspections
* des inspections
@ -129,7 +129,7 @@ Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modè
## Corps de la requête + paramètres de chemin { #request-body-path-parameters }
## 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*.
Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la même *chemin d'accès*.
**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**.
**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**.
@ -137,7 +137,7 @@ Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la
## Corps de la requête + paramètres de chemin et de requête { #request-body-path-query-parameters }
## 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*.
Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de **requête** dans la même *chemin d'accès*.
**FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit.
**FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit.
@ -153,7 +153,7 @@ Les paramètres de la fonction seront reconnus comme tel :
**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`.
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`.
L'annotation de type `str | None` 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.
Mais ajouter ces annotations de type permettra à votre éditeur de vous offrir un meilleur support et de détecter des erreurs.
@ -46,8 +46,8 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
to quit<b>)</b>
to quit<b>)</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><fontcolor="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><fontcolor="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>383153</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>383153</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color="#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
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()`.
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()`.
## Ordonner les paramètres comme vous le souhaitez, astuces { #order-the-parameters-as-you-need-tricks }
## Ordonner les paramètres comme vous le souhaitez, astuces { #order-the-parameters-as-you-need-tricks }
@ -81,15 +81,15 @@ Si vous voulez :
Passez `*`, comme premier paramètre de la fonction.
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 <abbrtitle="De : K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Même s'ils n'ont pas de valeur par défaut.
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 <abbrtitle="De : K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Même s'ils n'ont pas de valeur par défaut.
### Mieux avec `Annotated` { #better-with-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 `*`.
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 `*`.
@ -26,7 +26,7 @@ Cela vous apporte la prise en charge par l'éditeur dans votre fonction, avec v
///
///
## <abbrtitle="également appelé : sérialisation, parsing, marshalling">Conversion</abbr> de données { #data-conversion }
## <dfntitle="également appelé : sérialisation, parsing, marshalling">Conversion</dfn> de données { #data-conversion }
Si vous exécutez cet exemple et ouvrez votre navigateur sur <ahref="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 :
Si vous exécutez cet exemple et ouvrez votre navigateur sur <ahref="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 :
@ -38,7 +38,7 @@ Si vous exécutez cet exemple et ouvrez votre navigateur sur <a href="http://127
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 ».
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 ».
Ainsi, avec cette déclaration de type, **FastAPI** vous fournit automatiquement le <abbrtitle="conversion de la chaîne de caractères provenant d'une requête HTTP en données Python">« parsing »</abbr> de la requête.
Ainsi, avec cette déclaration de type, **FastAPI** vous fournit automatiquement le <dfntitle="conversion de la chaîne de caractères provenant d'une requête HTTP en données Python">« parsing »</dfn> de la requête.
///
///
@ -118,19 +118,19 @@ Et vous pouvez aussi avoir un chemin `/users/{user_id}` pour récupérer des don
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}` :
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}` :
Le premier sera toujours utilisé puisque le chemin correspond en premier.
Le premier sera toujours utilisé puisque le chemin correspond en premier.
## Valeurs prédéfinies { #predefined-values }
## Valeurs prédéfinies { #predefined-values }
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 <abbrtitle="Enumeration">`Enum`</abbr> Python standard.
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 <abbrtitle="Enumeration - Énumération">`Enum`</abbr> Python standard.
### Créer une classe `Enum` { #create-an-enum-class }
### Créer une classe `Enum` { #create-an-enum-class }
@ -140,11 +140,11 @@ En héritant de `str`, la documentation de l'API saura que les valeurs doivent
Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs valides disponibles :
Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs valides disponibles :
Si vous vous demandez, « AlexNet », « ResNet » et « LeNet » sont juste des noms de <abbrtitle="Techniquement, architectures de modèles de Deep Learning">modèles</abbr> de Machine Learning.
Si vous vous demandez, « AlexNet », « ResNet » et « LeNet » sont juste des noms de <dfntitle="Techniquement, architectures de modèles de Deep Learning">modèles</dfn> de Machine Learning.
///
///
@ -152,7 +152,7 @@ Si vous vous demandez, « AlexNet », « ResNet » et « LeNet » sont juste des
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`) :
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`) :
@ -47,40 +47,16 @@ C’est le moment de l’utiliser avec FastAPI. 🚀
Nous avions cette annotation de type :
Nous avions cette annotation de type :
//// tab | Python 3.10+
```Python
```Python
q: str | None = None
q: str | None = None
```
```
////
//// tab | Python 3.9+
```Python
q: Union[str, None] = None
```
////
Ce que nous allons faire, c’est l’englober avec `Annotated`, de sorte que cela devienne :
Ce que nous allons faire, c’est l’englober avec `Annotated`, de sorte que cela devienne :
//// tab | Python 3.10+
```Python
```Python
q: Annotated[str | None] = None
q: Annotated[str | None] = None
```
```
////
//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
```
////
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`.
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. 🎉
Passons maintenant aux choses amusantes. 🎉
@ -109,7 +85,7 @@ FastAPI va maintenant :
## Alternative (ancienne) : `Query` comme valeur par défaut { #alternative-old-query-as-the-default-value }
## Alternative (ancienne) : `Query` comme valeur par défaut { #alternative-old-query-as-the-default-value }
Les versions précédentes de FastAPI (avant <abbrtitle="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.
Les versions précédentes de FastAPI (avant <dfntitle="avant 2023-03">0.95.0</dfn>) 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
/// tip | Astuce
@ -191,7 +167,7 @@ Vous pouvez également ajouter un paramètre `min_length` :
## Ajouter des expressions régulières { #add-regular-expressions }
## Ajouter des expressions régulières { #add-regular-expressions }
Vous pouvez définir un `pattern` d’<abbrtitle="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 :
Vous pouvez définir un `pattern` d’<dfntitle="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</dfn> auquel le paramètre doit correspondre :
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 :
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 :
@ -371,7 +347,7 @@ Vous pouvez alors déclarer un `alias`, et cet alias sera utilisé pour trouver
Disons que vous n’aimez plus ce paramètre.
Disons que vous n’aimez plus ce paramètre.
Vous devez le laisser là quelque temps car des clients l’utilisent, mais vous voulez que les documents l’affichent clairement comme <abbrtitle="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 <dfntitle="obsolète, il est recommandé de ne pas l’utiliser">déprécié</dfn>.
Passez alors le paramètre `deprecated=True` à `Query` :
Passez alors le paramètre `deprecated=True` à `Query` :
@ -401,7 +377,7 @@ Pydantic a aussi <a href="https://docs.pydantic.dev/latest/concepts/validators/#
///
///
Par exemple, ce validateur personnalisé vérifie que l’ID d’item commence par `isbn-` pour un numéro de livre <abbrtitle="International Standard Book Number - Numéro international normalisé du livre">ISBN</abbr> ou par `imdb-` pour un ID d’URL de film <abbrtitle="IMDB (Internet Movie Database) est un site web contenant des informations sur les films">IMDB</abbr> :
Par exemple, ce validateur personnalisé vérifie que l’ID d’item commence par `isbn-` pour un numéro de livre <abbrtitle="International Standard Book Number - Numéro international normalisé du livre">ISBN</abbr> ou par `imdb-` pour un ID d’URL de film <abbrtitle="Internet Movie Database - Base de données de films sur Internet: un site web contenant des informations sur les films">IMDB</abbr> :
@ -435,7 +411,7 @@ Avez-vous remarqué ? Une chaîne utilisant `value.startswith()` peut prendre un
#### Un élément aléatoire { #a-random-item }
#### Un élément aléatoire { #a-random-item }
Avec `data.items()` nous obtenons un <abbrtitle="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.
Avec `data.items()` nous obtenons un <dfntitle="Quelque chose que l’on peut itérer avec une boucle for, comme une liste, un set, etc.">objet itérable</dfn> 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())`.
Nous convertissons cet objet itérable en une `list` propre avec `list(data.items())`.
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 ».
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 ».
La query est l'ensemble des paires clé-valeur placées après le `?` dans une URL, séparées par des caractères `&`.
La query est l'ensemble des paires clé-valeur placées après le `?` dans une URL, séparées par des caractères `&`.
@ -24,7 +24,7 @@ Mais lorsque vous les déclarez avec des types Python (dans l'exemple ci-dessus,
Tous les mêmes processus qui s'appliquaient 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 :
* Prise en charge de l'éditeur (évidemment)
* Prise en charge de l'éditeur (évidemment)
* <abbrtitle="conversion de la chaîne provenant d'une requête HTTP en données Python">« parsing »</abbr> des données
* <dfntitle="conversion de la chaîne provenant d'une requête HTTP en données Python">« parsing »</dfn> des données
* Validation des données
* Validation des données
* Documentation automatique
* Documentation automatique
@ -67,7 +67,7 @@ Dans ce cas, le paramètre de fonction `q` sera optionnel et vaudra `None` par d
/// check | Vérifications
/// check | Vérifications
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.
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.
///
///
@ -127,7 +127,7 @@ Si vous ne voulez pas leur donner de valeur spécifique mais simplement les rend
Mais si vous voulez rendre un paramètre de requête obligatoire, vous pouvez simplement ne déclarer aucune 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 :