Master 1 Humanités numériques – Bases de données Séance 4 : Publication de données sur le Web Objectif Extraire de la base Access conçue à la séance 1 des données relatives aux matières enseignées et les publier dans une page web : moyenne et nombre de notes par matières, sous forme de tableau ; nombre de notes par matière, sous forme de diagramme circulaire (camembert) ; moyennes par matière, sous forme de diagramme en bâtons ; moyennes par matière, sous forme de courbe (ce type de diagramme n’étant pas adapté pour ces données, c’est juste pour s’entraîner à l’utiliser car il est courant par ailleurs). Page web exemple : http://eric.univ-lyon2.fr/~jdarmont/docs/web/bd-web.html Prérequis Connexion Access Installer un pilote ODBC de même architecture que Python (32 ou 64 bits) http://eric.univ-lyon2.fr/~jdarmont/?page_id=3139#rs Installer le module Python PyPyODBC (il faut être administrateur de sa machine) https://pypi.python.org/pypi/pypyodbc Graphiques Python Installer le module Python MatPlotLib http://matplotlib.org/users/installing.html Extraction des données 1. Créer un fichier Python. Dans le code, importer le module PyPyODBC. 2. Écrire les instructions de connexion à la base de données Access (utiliser celle créée lors de la séance 1) et de fermeture de la connexion. Tester. Si Python ne renvoie pas d’erreur, ça fonctionne ! 3. Entre la connexion et sa fermeture, créer un curseur et exécuter la requête « intitulé de matière, moyenne des notes et nombre de notes, regroupés par intitulés et triés par intitulés ». Les sources de données nécessaires à cette requête sont les tables MATIERE, EPREUVE et PASSER (des jointures sont nécessaires). M1 HN – BASES DE DONNEES 1/3 Afin de pouvoir accéder aux agrégats (moyenne et compte), il faut les nommer à l’aide d’un alias, par exemple AVG(Note) AS Moyenne. Fermer le curseur. Tester. Si Python ne renvoie pas d’erreur, ça fonctionne… peutêtre ! 4. À des fins de vérification, à la suite de l’exécution de la requête, parcourir le curseur et afficher pour chacune de ses lignes l’intitulé de matière, la moyenne et le nombre de notes par matière. Tester. 5. Afin de faciliter la génération des graphiques, on va stocker les données du curseur dans trois listes : listeIntitules, listeMoyennes et listeNb. Juste avant le curseur, initialiser les trois listes à vide. Dans la boucle de parcours du curseur, ajouter à listeIntitules, listeMoyennes et listeNb l’intitulé de matière, la moyenne et le nombre de notes par matière, respectivement. L’affichage de ces données mis en place à la question 4 peut être mis en commentaire. Juste après la boucle, insérer l’instruction suivante, qui crée une plage de données indéterminées dont le nombre de valeurs est égal aux nombres de lignes du curseur. Cette liste servira à la création des graphiques. colonnes = range(len(listeIntitules)) 6. Vérifier que le code fonctionne. Génération de la page web 1. Après le code déjà écrit dans votre fichier Python, affectez à une variable de nom codeHTML et de type chaîne de caractères multiligne le début du code HTML d’une page web (<html><head>…</head><body>), puis définissez un tableau (<table>…</table>) de légende (<caption>…</caption>) « Moyenne et nombre de notes par matière » dont la ligne (<tr>…</tr>) d’entête contient trois colonnes (<th>…</th>) : Matière, Moyenne et Nb. 2. Dans une boucle « pour » sur la plage colonnes définie à la question 6 ci-dessus, concaténer à codeHTML une ligne (<tr>…</tr>) dont les colonnes de données (<td>…</td>) sont listeIntitules[i], listeMoyennes[i] et listeNb[i], en supposant que i soit l’indice de boucle. listeMoyennes[i] et listeNb[i] étant des nombres, il faut les convertir en chaîne de caractères lors de la concaténation (fonction str()). 3. Concaténer à codeHTML la fermeture des balises HTML encore ouvertes (</table></body></html>). 4. Ouvrir le fichier nommé bd-web.html en écriture, y écrire le contenu de codeHTML, fermer le fichier. 5. Tester la création du fichier HTML et vérifier son apparence en l’ouvrant dans un navigateur web. Le cas échéant, reprenez les étapes précédentes jusqu’à ce que le tableau s’affiche normalement dans le navigateur. M1 HN – BASES DE DONNEES 2/3 Inclusion de graphiques 1. Toujours dans le code déjà écrit dans votre fichier Python, importer le module MatPlotLib juste après PyPyODBC. 2. Après la fermeture de la connexion à la base de données et avant la génération du code HTML, créer un graphique de type camembert intitulé « Nombre de notes par matière » basé sur listeNb et listeIntitules. Afficher la figure en mode interactif (plt.show()). Tester. 3. Remplacer l’affichage interactif par la sauvegarde d’un fichier image (plt.savefig("camembert.png"), par exemple). 4. Dans la dernière partie de la génération de code HTML, ajouter une image (<img />) pointant sur camembert.png. 5. Tester et vérifier l’affichage du graphique inclus dans bd-web.html à l’aide d’un navigateur web. 6. Répéter les questions 2 à 5 pour : un diagramme en bâtons intitulé « Moyennes par matière » basé sur colonnes, listeMoyennes et listeIntitules ; une courbe également intitulée « Moyennes par matière » basée sur colonnes (les étiquettes de l’axe des abscisses sont textuelles), listeMoyennes et listeIntitules. M1 HN – BASES DE DONNEES 3/3 Correction # Access => graphiques => web import pypyodbc pypyodbc.lowercase = False import matplotlib.pyplot as plt # Connexion BD connexion = pypyodbc.connect( r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" + r"Dbq=d:\etu.accdb;") # Curseur curseur = connexion.cursor() curseur.execute( "SELECT Intitulé, AVG(Note) AS Moyenne, COUNT(Note) AS NbNotes FROM MATIERE M, EPREUVE E, PASSER P WHERE M.CodeMat = E.CodeMat AND E.CodeEpr = P.CodeEpr GROUP BY Intitulé ORDER BY Intitulé" ); # Préparation de listes de valeurs pour les graphiques listeIntitules = [] listeMoyennes = [] listeNb = [] for nuplet in curseur.fetchall(): # print(nuplet.get("Intitulé"), nuplet.get("Moyenne"), nuplet.get("NbNotes")) listeIntitules.append(nuplet.get("Intitulé")) listeMoyennes.append(nuplet.get("Moyenne")) listeNb.append(nuplet.get("NbNotes")) colonnes = range(len(listeIntitules)) # Fermeture curseur curseur.close() # Fermeture connexion connexion.close() # Création d'un camembert plt.title("Nombre de notes par matière") plt.pie(listeNb, labels = listeIntitules, startangle = 90, autopct = "%1.1f%%") plt.axis("equal") # Produit un cercle plutôt qu'une ellipse plt.savefig("camembert.png") #plt.show() # Affiche la figure en mode interactif plt.clf() # Fermeture figure M1 HN – BASES DE DONNEES 4/3 # Création d'un diagramme en bâtons plt.title("Moyennes par matière") plt.xlabel("Matière") plt.ylabel("Moyenne") plt.bar(colonnes, listeMoyennes, align = "center") plt.xticks(colonnes, listeIntitules) plt.savefig("batons.png") #plt.show() plt.clf() # Création d'une courbe plt.title("Moyennes par matière (pas adapté)") plt.xlabel("Matière") plt.ylabel("Moyenne") plt.plot(colonnes, listeMoyennes) plt.xticks(colonnes, listeIntitules) plt.savefig("courbe.png") #plt.show() plt.clf() # Génération du code HTML codeHTML = '''<!DOCTYPE html> <html> <head> <meta charset = "UTF-8" /> <title>Transfert Access -> Web + Graphiques</title> </head> <body> <h1>Tableau</h1> <table border="1"> <caption>Moyenne et nombre de notes par mati&egrave;re</caption> <tr> <th>Mati&egrave;re</th> <th>Moyenne</th> <th>Nb</th> </tr> ''' for i in colonnes: # Lignes du tableau codeHTML += "<tr> <td>" + listeIntitules[i] + "</td> <td>" + str(listeMoyennes[i]) + "</td> <td>" + str(listeNb[i]) + "</td> </tr>\n" codeHTML += '''</table> <h1>Camembert</h1> <p><img src="camembert.png" alt="Notes par mati&egrave;re" /></p> <h1>Diagramme en b&acirc;tons</h1> <p><img src="batons.png" alt="Moyennes par mati&egrave;re" /></p> <h1>Courbe</h1> <p><img src="courbe.png" alt="Moyennes par mati&egrave;re" /></p> </body> </html>''' M1 HN – BASES DE DONNEES 5/3 # Ecriture du fichier HTML f = open("bd-web.html", "w") f.writelines(codeHTML) f.close() M1 HN – BASES DE DONNEES 6/3