TP : Galerie d'images (flask)
Informations générales
Cours : Python Avancé > Web > Flask
Objectifs pédagogiques :
- Python avancé : framework Flask pour le développement web
- Outils modernes (poetry, PyCharm)
- Bonnes pratiques de l'entreprise
Prérequis
Installation et configuration de l’environnement
Installer les dépendances avec poetry install depuis un terminal PyCharm.
Connaissances préalables
- Connaissances de base en programmation
Énoncé
Contexte
L'objectif de ce TP Bonus est de développer une application web simple mais robuste avec le micro-framework Flask.
Vous êtes invité à lire les premières sections de la documentation officielle de Flask pour vous familiariser avec les concepts de base, avant de commencer le TP.
Cette application web affichera une galerie d'images à partir de fichiers stockés localement sur le serveur.
Les images étant fournies par le serveur avec différentes largeurs, cela permettra au client d'optimiser la performance réseau en fonction de la taille de l'image réelle à afficher côté client (navigateur).
Pour vous concentrer sur la logique métier et le fonctionnement de Flask, une partie significative du code vous est déjà fournie :
- Les templates HTML (
layout.html,gallery.html,404.html) qui gèrent l'affichage. - Les fichiers statiques (CSS Bootstrap) pour le design, ainsi que les images statiques.
- Un module utilitaire
utils.pycontenant une fonctionbuild_image_structurequi analyse et structure les données du répertoire contenant les images. - Une suite de tests automatisés (
test_app.py) qui vous permettra de valider votre travail au fur et à mesure.
Votre mission est de compléter le fichier src/app/views.py pour faire le lien entre les requêtes des utilisateurs, les données des images et les templates HTML.
Objectifs pédagogiques
À la fin de ce TP, vous saurez :
- Créer et organiser des routes (vues) dans une application Flask à l'aide de Blueprints.
- Faire le rendu de templates HTML en leur transmettant des données dynamiques (
render_template). - Gérer les erreurs de manière élégante (
try...except) pour rendre une application plus robuste. - Créer un premier endpoint d'API simple qui retourne des données au format JSON.
- Utiliser une suite de tests (Pytest) pour guider et valider votre développement (approche TDD-lite).
- Lancer et déboguer une application Flask localement.
Mise en place
Le projet utilise poetry pour la gestion des dépendances.
La structure du projet est la suivante :
.
├── poetry.lock
├── pyproject.toml
├── src
│ └── app
│ ├── __init__.py # Point d'entrée de l'application
│ ├── static/ # Fichiers CSS, et images
│ ├── templates/ # Fichiers HTML (templates Jinja2)
│ ├── utils.py # Fonctions utilitaires (fourni)
│ └── views.py # Le fichier à compléter !
└── tests
└── test_views.py # Tests pour valider votre code (fourni)
Travail à réaliser
Ouvrez le fichier src/app/views.py. Il est actuellement presque vide. Vous allez le compléter étape par étape.
Étape 1 : afficher la galerie d'images
Votre premier objectif est de créer la vue principale qui affiche la galerie.
Tâche : Créez une fonction index() qui répond à la route / (la racine du site).
Logique à implémenter dans la fonction index() :
-
Construisez le chemin vers le dossier contenant les images. Ce dossier se trouve dans
static/images. Utilisezcurrent_app.static_folderde Flask et la bibliothèquepathlibpour un code propre et portable. -
Appelez la fonction
build_image_structure()(importée depuis.utils) en lui passant le chemin du dossier des images. -
Rendez votre code robuste ! Encadrez l'appel à cette fonction dans un bloc
try...except. En cas d'erreur (par exemple, si le dossier n'existe pas ou si un autre problème survient), vous devez éviter que l'application ne plante.-
En cas de succès, vous passez les données des images au template.
-
Si aucune image n'est trouvée par la fonction, prévoyez un message d'erreur à afficher.
-
En cas d'exception, logguez l'erreur et préparez un message d'erreur générique pour l'utilisateur.
-
-
Faites le rendu du template
gallery.htmlen utilisantrender_template(). Vous devez lui passer deux variables :-
structured_images: Le dictionnaire d'images retourné parbuild_image_structure. -
error_message: Un message d'erreur (ouNonesi tout va bien).
-
Diagramme de flux (Étape 1) :
graph TD
subgraph Client[Navigateur]
A[Utilisateur]
end
subgraph Serveur[Serveur Flask]
B["Route /"]
C["views.py: index()"]
D["utils.py: build_image_structure()"]
E["templates/gallery.html"]
F[Réponse HTML]
end
subgraph SystemeFichiers[Disque Serveur]
G["static/images"]
end
A -- "1. Requête GET /" --> B
B -- "2. Déclenche" --> C
C -- "3. Construit chemin et appelle" --> D
D -- "4. Lit le dossier" --> G
G -- "5. Retourne la structure" --> D
D -- "6. Retourne dict_images" --> C
C -- "7. Injecte données dans" --> E
E -- "8. Génère" --> F
F -- "9. Envoie" --> A
Logique de gestion d'erreur (commune aux étapes 1 et 4) :
graph TD
A[Début de la vue] --> B{try}
B -- "Succès" --> C["Appel: build_image_structure()"]
C --> D{Images trouvées?}
D -- "Oui" --> E[Préparer réponse 200 OK - HTML ou JSON]
D -- "Non" --> F[Préparer réponse - HTML avec erreur ou JSON 404]
B -- "Échec" --> G[except Exception as e]
G --> H[Logguer l'erreur e]
H --> I[Préparer réponse - HTML avec erreur ou JSON 500]
E --> Z[Fin]
F --> Z[Fin]
I --> Z[Fin]
Étape 2 : valider avec les tests
Avant même de regarder le résultat dans votre navigateur, vérifiez que votre code est correct en lançant la suite de tests.
poetry run pytest -p no:warnings
Analysez le résultat. Certains tests qui échouaient au début devraient maintenant passer. L'objectif est de faire passer tous les tests relatifs à la galerie.
Étape 3 : lancer le serveur et constater le résultat
Une fois les tests au vert, lancez le serveur de développement Flask.
-
Assurez-vous d'être dans le bon dossier :
cd src -
Lancez le serveur en mode "debug" (ce mode recharge automatiquement le serveur à chaque modification de votre code) :
flask run --debug -
Ouvrez votre navigateur à l'adresse http://127.0.0.1:5000 et admirez votre galerie !
Étape 4 : créer un endpoint d'API JSON
Votre second objectif est de fournir les mêmes données via une API, au format JSON.
Tâche : Créez une fonction api_images() qui répond à la route /api/images.
Logique à implémenter :
-
La logique de récupération des données est la même que pour la vue
index(): chemin du dossier, appel àbuild_image_structure(), gestion des exceptions. -
La différence réside dans la réponse :
-
En cas de succès, retournez directement le dictionnaire
structured_images. Flask le convertira automatiquement en une réponse JSON avec un code de statut200 OK. -
Si aucune image n'est trouvée, retournez un dictionnaire d'erreur (ex:
{'error': "Aucune image n'a été trouvée"}) et le code de statut404 Not Found. -
En cas d'exception serveur, retournez un dictionnaire d'erreur (ex:
{'error': "Erreur interne du serveur"}) et le code de statut500 Internal Server Error.
-
Diagramme de flux (Étape 4) :
graph TD
subgraph Client[Client API ex: Postman, script]
A[Utilisateur/Service]
end
subgraph Serveur[Serveur Flask]
B[Route /api/images]
C["views.py: api_images()"]
D["utils.py: build_image_structure()"]
E[Réponse JSON]
end
subgraph SystemeFichiers[Disque Serveur]
G["static/images"]
end
A -- "1. Requête GET /api/images" --> B
B -- "2. Déclenche" --> C
C -- "3. Construit chemin et appelle" --> D
D -- "4. Lit le dossier" --> G
G -- "5. Retourne la structure" --> D
D -- "6. Retourne dict_images" --> C
C -- "7. Formate en JSON" --> E
E -- "8. Envoie" --> A
Étape 5 : ajouter un ou plusieurs tests pour l'API
Pour aller plus loin, ouvrez le fichier tests/test_app.py et ajoutez un ou plusieurs nouveaux tests pour votre API.
Idée de test :
Créez une fonction test_api_images_success() qui :
-
Fait un
GETsur/api/images. -
Vérifie que le code de statut est bien
200. -
Vérifie que le
content_typede la réponse est bienapplication/json. -
Vérifie que la réponse JSON contient des clés attendues (par exemple, le nom d'une des images).
Relancez les tests pour vous assurer que l'ancien et le nouveau code fonctionnent parfaitement.
Bonnes pratiques
-
La page d'accueil (
/) s'affiche correctement avec les images. Les images téléchargées par le navigateur sont cohérentes avec la taille réelles des images à afficher. -
La page gère correctement l'absence du dossier d'images sans planter, en affichant un message d'erreur.
-
L'endpoint
/api/imagesretourne une structure JSON valide en cas de succès. -
L'endpoint
/api/imagesretourne les codes d'erreur HTTP et les messages appropriés (404, 500). -
L'ensemble des tests fournis (et les vôtre) passent avec succès.
-
Le code dans
views.pyest clair, commenté et suit les bonnes pratiques Python.