Écrire des API avec Flask

Introduction

Dans ce TP nous allons créer des API à l’aide de Flask pour notre site web TodoList. Nous allons bien évidemment utiliser l’interface que vous avez développée dans le TP 1 VueJS. Ici nous allons recoder la partie « serveur » en python grâce au micro framework Flask.

Pour ne pas compliquer le TP je vais faire abstraction de la base de données, nous allons utiliser la session comme la première version de l’application.

Le main.py

Comme dans le premier TP notre code sera intégralement dans un fichier nommé « main.py ». Le fichier va contenir les différentes fonctions pour répondre aux différentes requêtes des clients.

Comme dans le premier TP, avant de commencer à coder nous allons déterminer le nom des fonctions ainsi que le chemin et les méthodes (POST, GET, DELETE, …):

DescriptionCheminMéthodeFonction
Liste
Création
Marquer comme terminé
Supprimer

Question :

  • C’est à vous, avant de continuer un papier un crayon ! Remplissez le tableau.
Voir l’une des solutions possibles

Structure de base

Créer un fichier main.py c’est ce fichier qui va contenir l’ensemble de votre code, comme dans la version PHP, nous allons utiliser le JSON pour communiquer.

Le minimum pour notre TP fonctionne est la déclaration des imports suivants :

import uuid
from flask import Flask, jsonify, request, session

Pour l’instant l’objet Flask n’est pas initialisé votre code n’est donc pas fonctionnel. Avant de continuer, regardons l’utilité des imports :

La partie Flask

Maintenant que vous avez compris l’usage des différents imports, nous allons initialiser Flask. Ajouter à la fin du fichier :

app = Flask(__name__)

if __name__ == '__main__':
    app.secret_key = 'YOLO_EXAMPLE_CHANGEME'
    app.run()

Vous pouvez maintenant lancer votre application, via :

python main.pys

Liste

Comme dans le premier TP, l’API list ne va faire que retourner la liste des tâches actuellement dans la session.

Avec Flask ça va être très simple ! Il suffit de faire :

return jsonify(session["todo"])

Très bien, mais on fait ça où ? Dans une fonction, il faut donc créer une fonction dans le fichier main.py pour le nom de la fonction je vous laisse vous reporter à votre tableau, pour le premier je vous aide :

@app.route("/api/todo")
def liste():
    """ Retourne la liste des todo dans la session """
    return jsonify(session["todo"])

🕵️‍♀️ Notez le commentaire dans la fonction… J’espère que vous allez en mettre vous aussi…

Question :

  • Comment être sure que la session est bien initialisée ?

Votre décorateur

Et voilà, c’est le moment… Le moment ou vous allez écrire votre propre décorateur ! (Si certains ont oublié ce que c’était un décorateur rendez-vous ici)

Très bien, maintenant que vous avez la mémoire fraiche, voilà votre décorateur :

from functools import wraps
from flask import session
def init_session(fn):
    """ Décorateur qui init la session """
    @wraps(fn)
    def wrap(*args, **kwargs):
        if "todo" not in session:
            session["todo"] = {}
        return fn(*args, **kwargs)
    return wrap

Où mettre le code ?

  • Choix 1 : Directement dans le main.py
  • Choix 2 : Dans un autre fichier (exemple helper.py)

Vous avez le choix… Si vous faites le choix de mettre le fichier dans un autre fichier, il faudra importer init_session dans le main.py :

from helper import init_session

PS Je vous conseille de le mettre dans un fichier helper.py.

Modification de la liste

Maintenant que votre décorateur est terminé, nous allons l’utiliser. Avant la fonction liste() ajouter @init_session() exemple :

@app.route("/api/todo")
@init_session # <-- Voilà ICI, ajouter l’appel au décorateur.
def liste():
    []

🎓 Le décorateur va être appelé avant chaque requête, votre session sera toujours bien créée, pratique non ?

Création

Comme dans le premier TP la partie création doit comporter un test :

  • Est-ce que e est dans data ?

Ce test s’écrit en Python :

[]
if "texte" in data:
    pass
else:
    pass
[]
  • L’autre élément important, c’est l’unicité d’une tâche dans la session, en python ça se fait avec :
import uuid
[]
uniq_id = str(uuid.uuid4())

Comme pour la liste, vous pouvez vous reporter à votre tableau contenant « le mapping » entre le chemin et la méthode, voilà ce que ça donne dans mon cas :

Cliquer pour afficher une solution possible

Questions :

  • Réaliser la methode dans votre code par rapport au tableau de définition que vous avez écrit.
  • À quoi sert request.form ? (Voir la doc de Flask)
  • Pourquoi ai-je fait « session.modified = True » ? À votre avis ? (La réponse est dans la documentation de Flask)

Marquer comme terminé

Marquer comme terminé une tache c’est changer le statut de « termine » à true.

  • Utiliser le décorateur d’initialisation de la session.
  • Vérifier que la tâche existe dans la session. (En python if current_id in session["todo"]:)
  • Récupérer la tâche dans la session.
  • Changer current['termine'] = True.
  • Sauvegarder à nouveau la tache dans la session.

Questions :

  • Écrire l’algorithme (en Français), du code à obtenir.
  • Le retranscrire en Python.
  • L’implémenter dans votre fichier main.py (en respectant le tableau établi)
Cliquer pour afficher une solution possible

Suppression

Supprimer une tâche, c’est tout simplement l’action de la retirer de la session, pour faire ça le mot-clé et python c’est del. Cependant votre code doit bloquer certaines actions, car toutes les tâches ne peuvent pas être supprimées :

  • Limiter l’action seulement aux « identifiants » reconnus dans la session.
  • La tâche doit avoir le booléen « termine » à vrai pour permettre la suppression.

Votre algorithme doit donc suivre :

  • Utiliser le décorateur qui initialise la session.
  • Vérifier que la tâche existe dans la session. (En Python if current_id in session["todo"]:)
  • Vérifier que la tâche à bien le statut termine == True. (en Python session["todo"][current_id]["termine"])
  • Suppression de la tâche (del …).
  • Sauvegarder à nouveau la tache dans la session.

Questions :

  • Écrire l’algorithme (en Français) du code à obtenir.
  • Le retranscrire en Python
  • L’implémenter dans votre fichier main.py (en respectant le tableau établi)
Cliquer pour afficher une solution possible

Tests

Maintenant que l’ensemble de votre code est terminé (et commenté 🕵🏻), nous allons pouvoir le tester, pour tester les API c’est plutôt simple. Il suffit d’utiliser des outils tels que Postmanopen in new window, l’idée c’est de se construire un « cahier » de test vous permettant de valider le fonctionnement de votre application rapidement (comprendre dès que vous modifiez le code). C’est dans ce but que je vous ai préparé une collection de « tests » qui devrait vous permettre de valider rapidement le bon fonctionnement de vos API.

Télécharger la collection de testsopen in new window

Question :

  • Valider le bon fonctionnement de votre application grâce au jeu de test.

Utilisation des API

Mettre à jour le code de votre TP « Ajouter VueJS dans un site existant » pour utiliser ces nouvelles API.