
Codez moins, expédiez plus rapidement : créer des API avec FastAPI
avec Python, la plupart des gens parlent de Django et Flask. Mais il existe une option plus récente et très rapide que de nombreux programmeurs Python commencent à aimer : FastAPI.
FastAPI est construit sur des fonctionnalités Python modernes, utilisant des astuces de type standard pour fournir gratuitement une validation automatique des données, une sérialisation et une documentation interactive sur l’API.
Le choix du framework approprié dépend de vos besoins. Django est un framework full-stack et Flask est connu pour sa simplicité. FastAPI, quant à lui, est conçu pour créer des API. Il se distingue par sa rapidité, sa facilité d’utilisation et sa capacité à réduire le code répétitif.
Alors, quand choisir FastAPI pour votre projet ?
- Vous créez un service centré sur l’API. FastAPI est conçu dès le départ à cet effet.
- Vous voulez que votre code soit votre documentation. Les documents automatiques de FastAPI changent la donne.
- Les performances sont essentielles. FastAPI est l’un des frameworks Python les plus rapides disponibles.
Que vous construisiez un petit microservice ou un backend complexe, savoir ce que FastAPI fait de mieux vous aidera à décider si cela vous convient. Vous tirerez le meilleur parti de cet article si vous connaissez déjà les principes fondamentaux des fonctions Python, des méthodes HTTP et de JSON.
Installation de FastAPI
Vous pouvez installer FastAPI avec uniquement les bases, mais il est préférable d’utiliser la configuration recommandée. De cette façon, vous obtenez tout ce dont vous avez besoin dès le début et vous n’avez pas à vous soucier des dépendances manquantes plus tard.
Avant de commencer, c’est une bonne idée de créer et d’activer un environnement virtuel. Cela permet de séparer les dépendances de votre projet et de garder votre système bien rangé. J’utilise UV pour cela, mais vous pouvez utiliser n’importe quel outil de votre choix. Bien que je travaille habituellement sous Windows, pour cet exemple, j’utiliserai Ubuntu WSL2 sous Windows. Je vais également exécuter le code dans un Jupyter Notebook, ce qui signifie ajouter un peu de code supplémentaire pour gérer la boucle d’événements de Jupyter, car elle peut entrer en conflit avec les fonctionnalités asynchrones de FastAPI.
tom@tpr-desktop:~$ uv init fastapi
Initialized project `fastapi` at `/home/tom/fastapi`
tom@tpr-desktop:~$ cd fastapi
tom@tpr-desktop:~/fastapi$ uv venv
Using CPython 3.13.0
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
tom@tpr-desktop:~/fastapi$ source .venv/bin/activate
(fastapi) tom@tpr-desktop:~/fastapi$
Pour bénéficier de l’expérience FastAPI complète, installez-le avec le [standard] des extras. Cela inclut l’outil de ligne de commande FastAPI et le serveur Uvicorn ASGI, dont vous aurez besoin pour exécuter votre application.
(fastapi) tom@tpr-desktop:~/fastapi$ uv pip install jupyter "fastapi[standard]"
Resolved 124 packages in 2.88s
Prepared 26 packages in 1.06s
Installed 124 packages in 80ms
+ annotated-types==0.7.0
+ anyio==4.11.0
+ argon2-cffi==25.1.0
...
...
...
+ webencodings==0.5.1
+ websocket-client==1.8.0
+ websockets==15.0.1
+ widgetsnbextension==4.0.14
(fastapi) tom@tpr-desktop:~/fastapi$
Pour vérifier que tout va bien, démarrez un Jupyter Notebook et saisissez le code suivant. Vous devriez recevoir un numéro de version en retour. Selon le moment où vous exécutez ce code, votre numéro de version sera probablement différent du mien.
import fastapi
print(fastapi.__version__)
# My Output
0.129.0
Nous sommes maintenant prêts à créer quelques applications.
Exemple 1 : Bonjour tout le monde
La création d’une application FastAPI de base ne nécessite que quelques lignes de code. Nous commencerons par un simple message « Hello World » pour illustrer les mécanismes de base du framework. Ne vous inquiétez pas, nos applications deviendront bientôt plus utiles. Tapez le code suivant dans une cellule du bloc-notes.
import nest_asyncio
import uvicorn
from fastapi import FastAPI
# Patch asyncio to allow nested use (needed in Jupyter/Colab)
nest_asyncio.apply()
app = FastAPI()
@app.get("/")
def home():
return {"message": "Hello, World!"}
# Use Config + Server instead of uvicorn.run()
config = uvicorn.Config(app=app, host="127.0.0.1", port=8000, log_level="info")
server = uvicorn.Server(config)
await server.serve()
Comme mentionné précédemment, un peu d’échafaudage supplémentaire est requis dans ce code car j’exécute dans un environnement Notebook, dont vous n’auriez généralement pas besoin si vous l’exécutiez en tant que module Python autonome. Pourtant, ce petit exemple en révèle déjà beaucoup. Vous importez FastAPI, créez une instance d’application et utilisez un décorateur (@app.get(« / »)) pour indiquer à FastAPI que la fonction home() doit gérer les requêtes GET vers le chemin racine. La fonction renvoie une simple chaîne de texte.
Lorsque vous exécutez le code ci-dessus, vous devriez voir un résultat similaire à celui-ci.
INFO: Started server process [28755]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Si vous cliquez maintenant sur l’URL dans la sortie ci-dessus, vous devriez voir quelque chose comme ceci.

Maintenant, construisons quelque chose de plus utile.
Exemple 2 : une liste de tâches fonctionnelle
Les API du monde réel doivent gérer les données. Développons notre code pour créer une simple API de liste de tâches en mémoire qui permettra des opérations CRUD complètes. Cela présentera les paramètres de chemin, les corps de demande et la validation des données.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
import uvicorn
import nest_asyncio
import threading
app = FastAPI()
# --- Pydantic Models for Data Validation ---
class TodoItem(BaseModel):
id: int
description: str
completed: bool = False
class CreateTodoItem(BaseModel):
description: str
class UpdateTodoItem(BaseModel):
description: Optional[str] = None
completed: Optional[bool] = None
# --- Dependency ---
async def common_query_params(completed: Optional[bool] = None, skip: int = 0, limit: int = 10):
return {"completed": completed, "skip": skip, "limit": limit}
# --- In-memory "database" ---
todos_db = {
1: TodoItem(id=1, description="Buy groceries"),
2: TodoItem(id=2, description="Walk the dog", completed=True),
3: TodoItem(id=3, description="Wash the car"),
4: TodoItem(id=4, description="Take out the trash", completed=True),
5: TodoItem(id=5, description="Watch TV"),
6: TodoItem(id=6, description="Play Golf", completed=True),
7: TodoItem(id=7, description="Eat breakfast"),
8: TodoItem(id=8, description="Climb Mt Everest", completed=True),
9: TodoItem(id=9, description="Work"),
10: TodoItem(id=10, description="Check the time", completed=True),
11: TodoItem(id=11, description="Feed the dog"),
12: TodoItem(id=12, description="Pick up kids from School", completed=True),
}
@app.get("/todos", response_model=List[TodoItem])
def get_all_todos():
"""Get all to-do items."""
return list(todos_db.values())
@app.get("/todos/{todo_id}", response_model=TodoItem)
def get_todo(todo_id: int):
"""Get a single to-do item by its ID."""
if todo_id not in todos_db:
raise HTTPException(status_code=404, detail="To-do item not found")
return todos_db[todo_id]
@app.post("/todos", response_model=TodoItem, status_code=201)
def create_todo(item: CreateTodoItem):
"""Create a new to-do item."""
new_id = max(todos_db.keys()) + 1
new_todo = TodoItem(id=new_id, description=item.description)
todos_db[new_id] = new_todo
return new_todo
@app.put("/todos/{todo_id}", response_model=TodoItem)
def update_todo(todo_id: int, item: UpdateTodoItem):
"""Update an existing to-do item."""
if todo_id not in todos_db:
raise HTTPException(status_code=404, detail="To-do item not found")
stored_item = todos_db[todo_id]
update_data = item.dict(exclude_unset=True)
updated_item = stored_item.copy(update=update_data)
todos_db[todo_id] = updated_item
return updated_item
@app.delete("/todos/{todo_id}", status_code=204)
def delete_todo(todo_id: int):
"""Delete a to-do item by its ID."""
if todo_id not in todos_db:
raise HTTPException(status_code=404, detail="To-do item not found")
del todos_db[todo_id]
return
# --- Code to run the Uvicorn server ---
# This is a wrapper function to run the server in a separate thread
def run_app():
uvicorn.run(app, host="0.0.0.0", port=8000)
# Apply the nest_asyncio patch
nest_asyncio.apply()
# Start the server in a new thread
# The daemon=True flag means the thread will exit when the main program exits.
thread = threading.Thread(target=run_app, daemon=True)
thread.start()
print("FastAPI server is running in the background.")
print("Access the API docs at http://127.0.0.1:8000/docs")
Il s’agit d’une mise à niveau significative ! Nous avons ajouté :
Modèles pydantiques. Nous avons défini les classes TodoItem, CreateTodoItem et UpdateTodoItem, qui héritent de BaseModel. FastAPI les utilise pour :
- Validation des données. S’il manque une description à une requête POST, FastAPI renvoie automatiquement une erreur 422 Unprocessable Entity avec un message clair.
- Sérialisation des données. Le paramètre Response_model dans les décorateurs garantit que la sortie correspond au modèle spécifié, ce qui est excellent pour la cohérence et la sécurité.
- Paramètres de chemin. Les fonctions get_todo et update_todo utilisent un paramètre de chemin {todo_id} pour identifier une ressource spécifique.
- Corps de la demande. Les fonctions create_todo et update_todo attendent un corps JSON qui correspond à leurs modèles Pydantic respectifs. FastAPI analyse, valide et convertit cela en un objet Python pour vous.
- Gestion des erreurs. Nous utilisons HTTPException pour renvoyer les codes d’erreur et les messages HTTP appropriés, comme un 404 Not Found.
Vous pouvez maintenant tester les points de terminaison GET dans votre navigateur. Pour récupérer une liste de tous les éléments TODO, tapez http://127.0.0.1:8000/todos dans votre navigateur. Vous devriez voir quelque chose comme ça.

Cochez la case Pretty-print pour voir le texte présenté au format JSON approprié.
De même, pour récupérer un identifiant particulier, disons ID = 3, saisissez l’URL suivante dans votre navigateur : http://127.0.0.1:8000/todos/3.
Pour les opérations POST, PUT et DELETE, il est temps d’utiliser l’une des meilleures fonctionnalités de FastAPI.
Tirez parti de votre documentation en direct
L’une des fonctionnalités les plus intéressantes de FastAPI est sa documentation API automatique et interactive. Vous l’obtenez gratuitement, simplement en écrivant du code Python standard.
Avec votre serveur en cours d’exécution, accédez à http://127.0.0.1:8000/docs. Vous verrez le Interface utilisateur Swaggerqui a analysé votre code et généré une interface complète pour votre API. Voici à quoi ressemblait ma page,

En utilisant cette page, vous pouvez :
- Affichez tous vos points de terminaison, y compris leurs méthodes HTTP et les docstrings correspondants.
- Inspectez les modèles de données exacts (schémas) requis pour les demandes et les réponses.
- Interagissez directement avec votre API. Par exemple, si vous développez le point de terminaison POST /todos, cliquez sur « Essayer », saisissez un corps JSON tel que {« description » : « Learn FastAPI »}, puis cliquez sur « Exécuter ». Vous venez d’ajouter un nouvel élément à votre liste !
FastAPI fournit également un style de documentation alternatif disponible sur http://127.0.0.1:8000/redoc. Cette documentation automatique et toujours synchronisée accélère considérablement le développement, les tests et la collaboration.
À titre d’exemple d’utilisation de l’interface utilisateur Swagger, disons que nous souhaitons supprimer l’élément 8 : non, je n’ai pas vraiment gravi le mont Everest ! Cliquez sur le bouton SUPPRIMER sur la page de l’interface utilisateur Swagger. Remplissez le numéro d’identification en le définissant sur 8. Votre page devrait ressembler à ceci.

À partir de là, vous pouvez soit cliquer sur le bouton Exécuter, soit utiliser l’expression curl fournie. L’enregistrement correspondant à ID=8 sera supprimé de votre « base de données ». Vous pouvez vérifier que tout a bien fonctionné en récupérant toutes les tâches.
Implémentez Ne vous répétez pas (DRY) avec des dépendances
Au fur et à mesure que votre API se développe, vous vous retrouverez à répéter la logique. Vous devez peut-être vérifier les clés API, établir des connexions à la base de données ou analyser les paramètres de requête standard pour la pagination. API rapides Injection de dépendance Le système est une solution élégante à cela.
Une dépendance est simplement une fonction que FastAPI exécute avant votre fonction d’opération de chemin. Créons une dépendance pour gérer les paramètres de requête standard afin de filtrer notre liste de tâches.
# --- Dependency ---
# Set the max number of records to retrieve
# Also only retrieve records marked as Completed
async def common_query_params(completed: Optional[bool] = None, skip: int = 0, limit: int = 10):
return {"completed": completed, "skip": skip, "limit": limit}
Cette fonction définit quelques paramètres de requête facultatifs pour limiter le nombre et l’état des tâches que nous récupérerons. Désormais, nous pouvons « en dépendre » dans notre fonction path. Modifions get_all_todos pour l’utiliser :
# Add this import at the top
from fastapi import Depends
...
@app.get("/todos", response_model=List[TodoItem])
def get_all_todos(params: dict = Depends(common_query_params)):
"""
Get all to-do items, with optional filtering by completion status and pagination.
"""
items = list(todos_db.values())
if params["completed"] is not None:
items = [item for item in items if item.completed == params["completed"]]
return items[params["skip"]:params["skip"] + params["limit"]]
...
...
Désormais, FastAPI va :
- Voyez que get_all_todos dépend de common_query_params.
- Appelez d’abord common_query_params, en transmettant tous les paramètres de requête correspondants à partir de l’URL (par exemple, /todos?completed=true&limit=3).
- Prenez la valeur de retour de la dépendance ({« completed »: True, …}) et transmettez-la à votre fonction path comme argument params.
Les dépendances sont une fonctionnalité puissante qui vous aide à écrire du code plus propre, plus modulaire et plus réutilisable. Vous pouvez les utiliser pour l’authentification, les sessions de base de données et à bien d’autres fins.
Pour essayer cela, cliquez à nouveau sur l’interface utilisateur Swagger, puis cliquez sur le bouton OBTENIR pour toutes les tâches. Remplissez les formulaires comme indiqué ci-dessous.

Désormais, lorsque vous exécutez ceci (ou utilisez la commande curl donnée), vous ne devriez voir qu’un maximum de 3 enregistrements où le statut terminé de chaque tâche est défini sur True. Et c’est précisément ce que nous obtenons.
[
{
"id": 2,
"description": "Walk the dog",
"completed": true
},
{
"id": 4,
"description": "Take out the trash",
"completed": true
},
{
"id": 6,
"description": "Play Golf",
"completed": true
}
]
Résumé
Vous avez maintenant vu un aperçu complet de ce qui fait de FastAPI un choix incontournable pour le développement d’API.
Dans ce guide, vous avez appris à :
- Installer FastAPI avec son ensemble d’outils recommandé.
- Construire une API fonctionnelle avec validation des données, paramètres de chemin et corps de requête.
- Utiliser la documentation interactive automatique pour les tests et l’exploration.
- Gardez votre code propre et réutilisable avec le puissant système d’injection de dépendances de FastAPI.
La conception moderne de FastAPI, ses excellentes performances et l’accent mis sur l’expérience des développeurs en font un choix idéal pour tout nouveau projet d’API Python. Les fonctionnalités de validation automatique et de documentation à elles seules peuvent vous faire gagner d’innombrables heures, vous permettant de vous concentrer sur la création de fonctionnalités plutôt que sur l’écriture de code passe-partout.
Je n’ai fait qu’effleurer la surface de la bibliothèque FastAPI et de ses capacités. Pour plus d’informations, consultez la page FastAPI GitHub à l’adresse :



