Démarrer avec Flask : Servir des Données et Manipuler du JSON

@joekakone

Joseph Konka @joekakone

03/03/2026 · 7 min

Concevez votre premier serveur d'API avec Flask : comprenez les méthodes HTTP GET et POST, gérez les paramètres d'URL, validez les requêtes entrantes et renvoyez des agrégats sous forme de JSON structuré.

Une API de données a une mission fondamentale : recevoir des requêtes de machines clientes, exécuter un calcul ou une interrogation, et renvoyer une réponse propre au format JSON.

Dans cette leçon, nous allons dépasser le classique "Hello World" pour construire un premier micro-service analytique capable d'ingérer des paramètres et de renvoyer des indicateurs calculés.


🌐 Les Deux Méthodes HTTP Clés pour la Data : GET et POST#

En tant qu'analyste de données ou ingénieur MLOps, vous utiliserez quasi-exclusivement deux verbes du protocole HTTP :

┌────────────────────────────────────────────────────────┐
│ 1. MÉTHODE GET : Demander des Données Existantes       │
│ Client ──► "Donne-moi les ventes du magasin Paris"     │
│ ──► Paramètres visibles dans l'URL (?region=Paris)     │
│ ──► Utilisé pour : /health, /metrics, /reports         │
└────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────┐
│ 2. MÉTHODE POST : Envoyer des Données pour Traitement   │
│ Client ──► "Voici les caractéristiques d'un client...  │
│             calcule-moi sa probabilité de churn !"     │
│ ──► Données transmises dans le corps (Body JSON)       │
│ ──► Utilisé pour : /predict, /train, /batch-score      │
└────────────────────────────────────────────────────────┘

🏗️ Anatomie d'un Micro-Service Analytique#

Créez un fichier nommé app.py et observez la mise en place de ces deux méthodes :

app.py : Serveur analytique avec routes GET et POST
from flask import Flask, jsonify, request

app = Flask(__name__)

# 1. Endpoint de santé système (Health Check)
@app.route("/api/v1/health", methods=["GET"])
def health_check():
    """Vérifie que l'API est active et prête à recevoir du trafic."""
    return jsonify({
        "status": "healthy",
        "service": "Analytics & Scoring Engine",
        "version": "1.0.0"
    }), 200

# 2. Endpoint avec paramètre d'URL dynamique (Filtrage)
@app.route("/api/v1/kpis/<region>", methods=["GET"])
def get_regional_kpis(region):
    """Renvoie les indicateurs clés pour une région géographique spécifique."""
    # Simulation d'un filtre sur un DataFrame
    kpi_db = {
        "europe": {"chiffre_affaires": 850000, "croissance": 0.14, "clients_actifs": 1240},
        "amerique": {"chiffre_affaires": 1250000, "croissance": 0.22, "clients_actifs": 2100},
        "afrique": {"chiffre_affaires": 420000, "croissance": 0.35, "clients_actifs": 890}
    }

    result = kpi_db.get(region.lower())
    if not result:
        return jsonify({"erreur": f"La région '{region}' est introuvable."}), 404

    return jsonify({"region": region.capitalize(), "kpis": result}), 200

# 3. Endpoint POST recevant un payload JSON (Préparation au scoring)
@app.route("/api/v1/simulate-basket", methods=["POST"])
def simulate_basket():
    """Reçoit une liste d'articles et calcule le montant TTC et la remise."""
    payload = request.get_json()

    # Validation minimale de l'entrée
    if not payload or "articles" not in payload:
        return jsonify({"erreur": "Payload JSON invalide. Clé 'articles' requise."}), 400

    articles = payload["articles"]
    total_ht = sum(item.get("prix", 0) * item.get("quantite", 1) for item in articles)

    # Règle métier : 10% de remise si le panier dépasse 100 €
    remise = total_ht * 0.10 if total_ht > 100 else 0.0
    total_ttc = (total_ht - remise) * 1.20 # TVA 20%

    return jsonify({
        "nb_articles": len(articles),
        "total_ht": round(total_ht, 2),
        "remise_appliquee": round(remise, 2),
        "total_ttc": round(total_ttc, 2)
    }), 200

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

🚀 Lancer et Tester l'Application#

1. Démarrer le serveur#

Dans votre terminal (avec l'environnement virtuel actif) :

python app.py
Sortie de démarrage dans la console
 * Serving Flask app 'app'
 * Debug mode: on
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
Aperçu d'une réponse Flask dans le navigateur

2. Tester les requêtes avec Python (requests)#

Ouvrez un second terminal ou un notebook Python pour simuler les appels d'un client externe :

test_client.py : Script de validation des endpoints
import requests

BASE_URL = "http://127.0.0.1:5000/api/v1"

# Test 1 : Health Check (GET)
res_health = requests.get(f"{BASE_URL}/health")
print("Health Check :", res_health.json())

# Test 2 : KPIs Régionaux (GET avec paramètre)
res_kpis = requests.get(f"{BASE_URL}/kpis/europe")
print("KPIs Europe  :", res_kpis.json())

# Test 3 : Simulation de panier (POST avec payload JSON)
mon_panier = {
    "articles": [
        {"nom": "Écran 27 pouces", "prix": 180.0, "quantite": 1},
        {"nom": "Câble HDMI", "prix": 15.0, "quantite": 2}
    ]
}
res_basket = requests.post(f"{BASE_URL}/simulate-basket", json=mon_panier)
print("Simulation   :", res_basket.json())

Exécutez ce script de test :

Output de test_client.py
Health Check : {'service': 'Analytics & Scoring Engine', 'status': 'healthy', 'version': '1.0.0'}
KPIs Europe  : {'kpis': {'chiffre_affaires': 850000, 'clients_actifs': 1240, 'croissance': 0.14}, 'region': 'Europe'}
Simulation   : {'nb_articles': 2, 'remise_appliquee': 21.0, 'total_ht': 210.0, 'total_ttc': 226.8}

⚠️ Les Codes d'État HTTP à Respecter Impérativement#

Une API professionnelle ne renvoie pas un simple message textuel en cas de pépin : elle utilise les codes de statut HTTP normés pour avertir le client :

  • 200 OK : Le calcul a réussi, la réponse est dans le JSON.
  • 201 Created : Une nouvelle ressource a été enregistrée avec succès.
  • 400 Bad Request : Le JSON envoyé par le client est malformé ou il manque une variable prédictive obligatoire.
  • 404 Not Found : La route demandée ou l'identifiant n'existe pas.
  • 500 Internal Server Error : Une exception Python non gérée a crashé sur le serveur (à éviter absolument grâce à des blocs try...except).

Vous maîtrisez désormais les flux de données entrants et sortants dans Flask. Cependant, placer l'intégralité de son code dans un seul fichier app.py devient ingérable dès que le projet grandit. Dans la prochaine leçon, nous allons structurer notre projet selon les standards de l'industrie.

Commentaires

Inscrivez-vous à une formation complète

Voir le catalogue