Comme vous l'avez remarqué, la valeur reçue par la fonction (et renvoyée ensuite) est 3,
en tant qu'entier (int) Python, pas la chaîne de caractères (string) "3".
Grâce aux déclarations de types, FastAPI fournit du
"parsing" automatique.
Et quand vous vous rendez sur http://127.0.0.1:8000/docs, vous verrez la
documentation générée automatiquement et interactive :
Info
À nouveau, en utilisant uniquement les déclarations de type Python, FastAPI vous fournit automatiquement une documentation interactive (via Swagger UI).
On voit bien dans la documentation que item_id est déclaré comme entier.
Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative.¶
Le schéma généré suivant la norme OpenAPI,
il existe de nombreux outils compatibles.
Grâce à cela, FastAPI lui-même fournit une documentation alternative (utilisant ReDoc), qui peut être lue
sur http://127.0.0.1:8000/redoc :
De la même façon, il existe bien d'autres outils compatibles, y compris des outils de génération de code
pour de nombreux langages.
Toute la validation de données est effectué en arrière-plan avec Pydantic,
dont vous bénéficierez de tous les avantages. Vous savez donc que vous êtes entre de bonnes mains.
Quand vous créez des fonctions de chemins, vous pouvez vous retrouver dans une situation où vous avez un chemin fixe.
Tel que /users/me, disons pour récupérer les données sur l'utilisateur actuel.
Et vous avez un second chemin : /users/{user_id} pour récupérer de la donnée sur un utilisateur spécifique grâce à son identifiant d'utilisateur
Les fonctions de chemin étant évaluées dans l'ordre, il faut s'assurer que la fonction correspondant à /users/me est déclarée avant celle de /users/{user_id} :
fromfastapiimportFastAPIapp=FastAPI()@app.get("/users/me")asyncdefread_user_me():return{"user_id":"the current user"}@app.get("/users/{user_id}")asyncdefread_user(user_id:str):return{"user_id":user_id}
Sinon, le chemin /users/{user_id} correspondrait aussi à /users/me, la fonction "croyant" qu'elle a reçu un paramètre user_id avec pour valeur "me".
Si vous avez une fonction de chemin qui reçoit un paramètre de chemin, mais que vous voulez que les valeurs possibles des paramètres soient prédéfinies, vous pouvez utiliser les Enum de Python.
Importez Enum et créez une sous-classe qui hérite de str et Enum.
En héritant de str la documentation sera capable de savoir que les valeurs doivent être de type string et pourra donc afficher cette Enum correctement.
Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs autorisées pour cette énumération.
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Créez ensuite un paramètre de chemin avec une annotation de type désignant l'énumération créée précédemment (ModelName) :
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Vous pouvez comparer ce paramètre avec les membres de votre énumération ModelName :
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Vous pouvez obtenir la valeur réel d'un membre (une chaîne de caractères ici), avec model_name.value, ou en général, votre_membre_d'enum.value :
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Astuce
Vous pouvez aussi accéder la valeur "lenet" avec ModelName.lenet.value.
Vous pouvez retourner des membres d'énumération dans vos fonctions de chemin, même imbriquée dans un JSON (e.g. un dict).
Ils seront convertis vers leurs valeurs correspondantes (chaînes de caractères ici) avant d'être transmis au client :
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Le client recevra une réponse JSON comme celle-ci :
OpenAPI ne supporte pas de manière de déclarer un paramètre de chemin contenant un chemin, cela pouvant causer des scénarios difficiles à tester et définir.
Néanmoins, cela reste faisable dans FastAPI, via les outils internes de Starlette.
Et la documentation fonctionne quand même, bien qu'aucune section ne soit ajoutée pour dire que la paramètre devrait contenir un chemin.