Dans ce tutoriel, vous allez apprendre à structurer proprement une application FastAPI en plusieurs fichiers et modules Python, en séparant vos routes, votre configuration et votre point d’entrée.
Pour bien suivre, commencez par ces guides si ce n’est pas déjà fait :
Objectifs :
- Comprendre pourquoi et comment découper un projet FastAPI en plusieurs fichiers
- Utiliser
APIRouter
etinclude_router
pour organiser les endpoints - Mettre la route de statut
/info/status
dans un fichier dédié - Préparer le terrain pour la configuration et l’extension de l’application
Pourquoi séparer en plusieurs fichiers ?
- Lisibilité : chaque fichier a une responsabilité claire (routes, config, démarrage)
- Évolutivité : ajouter un nouveau domaine fonctionnel = ajouter un nouveau router
- Testabilité : des modules plus petits facilitent l’écriture de tests unitaires
- Ré-utilisabilité : mieux isolé, le code est plus facile à partager et à refactorer
Structure de projet proposée
Voici une structure simple et efficace pour des APIs de taille petite à moyenne :
.
├── app
│ ├── __init__.py
│ ├── main.py # Création de l'app et inclusion des routers
│ └── routers
│ ├── __init__.py
│ ├── exemple.py # Router d'exemple
│ └── status.py # Router dédié au statut/healthcheck
├── requirements.txt
└── README.md (optionnel)
app/main.py
contient l’instance FastAPI et inclut les routersapp/routers/status.py
définit le router pour/info/status
app/routers/exemple.py
définit le router pour/exemple/*
app/routers/__init__.py
peut rester vide, il marque le dossier comme package Python
Remarque : si vous avez suivi l’article sur Docker, la route
/info/status
reste la même. VotreDockerfile
et sa healthcheck HTTP continueront de fonctionner sans modification.
Implémentation pas à pas
1) Créer le router de statut (fichier dédié)
Créez app/routers/status.py
:
from fastapi import APIRouter
router = APIRouter(prefix="/info", tags=["status"]) # préfixe commun à toutes les routes de ce router
@router.get("/status")
def info_status():
# Réponse adaptée aux checks de disponibilité (k8s, Docker, etc.)
return {"status": "ok"}
2) Créer l’application et inclure le router
Créez app/main.py
:
from fastapi import FastAPI
from .routers.status import router as status_router
from .routers.exemple import router as exemple_router
def create_app() -> FastAPI:
app = FastAPI()
# Exemple d'endpoint "racine" minimal
@app.get("/")
def root():
return "Hello World"
# On branche nos routers ici
app.include_router(status_router)
app.include_router(exemple_router)
return app
# Uvicorn cherchera cette variable exportée
app = create_app()
3) Marquer les dossiers comme packages Python
Créez des fichiers vides app/__init__.py
et app/routers/__init__.py
pour
permettre les imports relatifs (si ce n’est pas déjà le cas dans votre
environnement).
Contenu (peut rester vide) :
# app/__init__.py
# app/routers/__init__.py
Lancer l’application
Depuis la racine du projet :
uvicorn app.main:app --reload
Par défaut, l’API sera disponible sur http://127.0.0.1:8000
- Test manuel :
curl http://127.0.0.1:8000/
# "Hello World"
curl http://127.0.0.1:8000/info/status
# {"status":"ok"}
- Documentation automatique :
- Swagger UI : http://127.0.0.1:8000/docs
- Redoc : http://127.0.0.1:8000/redoc
Étendre l’application : ajouter d’autres routers
La force de cette approche est de pouvoir ajouter facilement de nouveaux
domaines fonctionnels.
Par exemple, vous pouvez créer app/routers/users.py
avec son propre
APIRouter(prefix="/users")
et l’inclure via app.include_router(users_router)
dans create_app()
.
Cette organisation facilite :
- la séparation par domaine (users, items, auth, etc.)
- l’ajout de middlewares ou de dépendances au niveau d’un router
- la lecture et la maintenance du code sur le long terme
Résumé
- Nous avons découpé l’application FastAPI en modules : un point d’entrée (
app/main.py
) et un fichier dédié pour la route de statut (app/routers/status.py
). - Nous avons utilisé
APIRouter
etinclude_router
pour organiser et brancher les endpoints. - Cette structure améliore la lisibilité et prépare l’application à grandir proprement.