Développer un site interactif avec formulaire et ajax
Objectifs et données
Pour commencer, on dispose sur notre serveur de :
3000 extraits musicaux de 15 s
d'un fichier de type csv, contenant une ligne par extrait musical : 4 champs séparés par des ; groupe ;album ;titre ;chemin vers le fichier
d'un interpréteur python (python cgi sur apache2)
D'un gestionnaire de fichier en ligne pour éditer / transférer / gérer les droits des fichiers
L'édition de fichiers pythons en ligne n'est pas aisée avec cet éditeur ( gestion de l'indentation) , pour cela on dispose également d'un accès webdav qui permet l'usage d'un éditeur plus adapté.
Le travail à réaliser :
On cherche à faire une sorte de jukebox en ligne, l'utilisateur choisira dans un premier temps le groupe, puis l'album, puis l'extrait musical à jouer .
Les objectifs liés au programme :
Représentation des données : types construits
Type dictionnaire pour passer les commandes à l'interface
Dictionnaires par clés / valeurs
Traitement de données en tables :
Indexation de tables
Recherche dans une table
Tri d'une table
Fusion d'un table
Interactions entre l'homme et la machine sur le Web
Modalités de l'interaction entre l'homme et la machine
Interaction avec l'utilisateur dans une page Web
Interaction client-serveur. Requêtes HTTP, réponses du serveur
Formulaire d'une page Web
Partie python : le traitement des données
Les différentes étapes
On adopte une structure de type web pour préparer la suite de la réalisation.
Comme on travaillera avec des scripts cgi python avec des formulaires, puis ajout d'ajax, autant préparer la structure et les affichages en conséquences .
Dans le répertoire cgi, on trouve deux fichiers :
fonctions.py contenant que l'on utilisera comme bibliothèque pour alléger la page contenant les codes
ressources.py qui permet de récupérer les données envoyées par les formulaires et renvoyer les réponses
Les instructions seront passées au fichier ressources via des formulaires.
On utilisera pour le fichier ressources.py des couples clefs / valeurs stockées dans un dictionnaire nommé choix. La clef action pour l'action à réaliser , puis la variable fichier qui contiendra l'emplacement du fichier à traiter. Celui-ci ne changera pas au cours de l"activité, mais sur le prinvipe il est bon de la prévoir comme variable.
On désire extraire à partir du fichier listeok.csv dans l'ordre :
La liste des artistes (action :voirArtistes)
La liste des albums d'un artiste (action :voirAlbums), dans ce cas, notre dictionnaire devra également contenir l'artiste dont on veut voir les albums (artiste : artiste choisi au 1)
La liste des morceaux d'un album(action :voirMorceaux), dans ce cas, notre dictionnaire devra contenir l'album choisi précédemment (album : album choisi au 2)
Le morceau à jouer, Enfin ! (action :jouerMorceau) et lemorceau : . ;le morceau choisi).
Quelques exemples :
choix = {'action':'voirArtistes','fichier':'../data/listeok.csv'} pour afficher les artistes
choix = {'action':'voirMorceaux','fichier':'../data/listeok.csv','album' :'The Alice Cooper Show'}
La structure de départ
Pour commencer, on présente la structure de départ
Ci dessous , la structure de départ, attention, le serveur hébergeant les site possède ses propres ressources :
/nsi/components/jquery-3.3.1.min.js pour le jquery (bibliothèques javascript utilisée plus tard)
/nsi/components/bootstrap/css/bootstrap.min.css (bibliothèque css pour gagner du temps)

La partie WEB - comprendre le principe ..
Structures des pages
La page qui servira d'interface avec l'utilisateur : index.html
Pour l'instant le javascript est commenté
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Musiques </title>
<link href="/nsi/components/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="../css/default.css">
</head>
<body>
<header>
<!-- Fixed navbar -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Le mini projet JBK: - page de tests </a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="../../1nsi.html">Retour accueil</a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.html">Ma page </a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</header>
<!--
Début du corps de la page
-->
<div class="container">
<div class="row">
<!--Colonne de gauche-->
<div class="col-sm gauche">
<h1> Les artistes</h1>
</div>
<!--colonne du milieu -->
<div class="col-sm milieu">
<h1> Les albums </h1>
</div>
<!-- colonne de droite-->
<div class="col-sm droit">
<h1>Les morceaux</h1>
</div>
</div>
</div>
<!--
<script src="/nsi/components/jquery-3.3.1.min.js"></script>
<script src="../js/default.js"></script>
-->
</body>
</html>
Pour commencer, on va utiliser le fichier tests.html, pour mettre au point les fichiers python.
Ce fichier propose différentes méthodes pour faire des requêtes au fichier ressources.py
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Musiques </title>
<link href="/nsi/components/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="../css/default.css">
</head>
<body class="test">
<header>
<!-- Fixed navbar -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Le mini projet JBK: - page de tests </a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="../../1nsi.html">Retour accueil</a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.html">Ma page </a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</header>
<!--
Début du corps de la page
-->
<div class="container">
<H1>Les tests ...</H1>
<div class="row">
<!--Colonne de gauche-->
<div class="col-sm gauche">
<h1> Sous forme d'url (méthode get)</h1>
Afficher les artistes:<br />
<a href="../cgi/ressources.py?afaire=voirArtistes">voir les artistes</a><br />
<!-- toujours sous forme de liens direct, mais le choix est déjà fait-->
Afficher les albums d'aerosmith:<br/>
<a href="../cgi/ressources.py?afaire=voirArtistes&artiste=Aerosmith">voir les albums d'Aerosmith</a><br/>
Afficher les morceaux de l'album Arrêt sur images:<br/>
<a href="../cgi/ressources.py?afaire=voirAlbums&album=Arrêt+sur+image"> Voir les titres</a>
</div>
<div class="col-sm milieu">
<h1> Formulaires get</h1>
<!--
demande affichage artiste , une seule variable, on lui donne le nom "afaire", inutile d'afficher la variable
-->
Premier formulaire: afficher les artistes ...<br />
<form action="../cgi/ressources.py" method="get" >
<input type="hidden" name="afaire" value="voirArtistes" >
<input type="submit" class="btn btn-success" value="Voir les artistes">
<!-- changer le type de bouton, voir ici:https://getbootstrap.com/docs/4.0/components/buttons/-->
</form>
<hr />
<!--
demande affichage des albums d'un artiste , deux variables, "afaire" qui vaut "voirAlbums" et un choix d'artistes en menu déroulant
par la suite ce menu devra être chargé automatiquement avec tous les artistes
-->
Deuxième formulaire : afficher les albums de l'artiste choisi ...<br />
<form action="../cgi/ressources.py" method="get" >
<input type="hidden" name="afaire" value="voirArtistes" >
Choisir l'artiste <br />
<select name="artiste">
<option value="Alice Cooper">Alice cooper </option>
<option value="Aerosmith">Aerosmith</option>
</select>
<input type="submit" class="btn btn-success" value="Voir les albums">
</form>
<hr />
<!--
demande affichage des morceaux d'un album, deux variables, "afaire" qui vaut "voirAlbums" et un choix d'albums en menu déroulant
par la suite ce menu devra être chargé automatiquement avec tous les albums.
On aurait mu palcer en type hidden le nom de l'artiste ... au cas ou
-->
Troisème formulaire : afficher les albums de l'artiste choisi ...<br />
<form action="../cgi/ressources.py" method="get" >
<input type="hidden" name="afaire" value="voirAlbums" >
Choisir l'album <br />
<input type="radio" value="Carnets de bord" name="album">Carnets de bord <br />
<input type="radio" value="Arrêt sur image" name="album">Arrêt sur image <br />
<input type="radio" value="If" name="album">If <br />
<input type="submit" class="btn btn-success" value="Voir les morceux de cet album">
</form>
</div>
<!-- colonne de droite-->
<div class="col-sm droit">
<h1>Formulaires post</h1>
Premier formulaire: afficher les artistes ...<br />
<form action="../cgi/ressources.py" method="post" >
<input type="hidden" name="afaire" value="voirArtistes" >
<input type="submit" class="btn btn-success" value="Voir les artistes">
</form>
<hr />
Deuxième formulaire : afficher les albums de l'artiste choisi ...<br />
<form action="../cgi/ressources.py" method="get" >
<input type="hidden" name="afaire" value="voirArtistes" >
Choisir l'artiste <br />
<select name="artiste">
<option value="Alice Cooper">Alice cooper </option>
<option value="Aerosmith">Aerosmith</option>
</select>
<input type="submit" class="btn btn-success" value="Voir les albums">
</form>
<hr />
Troisème formulaire : afficher les albums de l'artiste choisi ...<br />
<form action="../cgi/ressources.py" method="post" >
<input type="hidden" name="afaire" value="voirAlbums" >
Choisir l'album <br />
<input type="radio" value="Carnets de bord" name="album">Carnets de bord <br />
<input type="radio" value="Arrêt sur image" name="album">Arrêt sur image <br />
<input type="radio" value="If" name="album">If <br />
<input type="submit" class="btn btn-success" value="Voir les morceux de cet album">
</form>
</div>
</div>
</div>
<!--
<script src="/nsi/components/jquery-3.3.1.min.js"></script>
<script src="../js/default.js"></script>
-->
</body>
</html>
les fichiers python, la bibliothèque fonctions.py et dessous le fichiers ressources.py
#!/usr/bin/python3
# * coding: UTF8 *
#renvoie Faux si l'artise est dans la liste
def TestDoublons(liste,artiste):
for i in liste:
pass
return False
#Ajoute un artiste à une liste en évitant les doublons
def AjouteA(liste,artiste):
#on teste les doublons
pass
return
#charge les albums d'un artiste
def GetAlbums(artiste,lines):
Albums =[]
for ligne in lines:
pass
return Albums
#charge les morceaux d'un album
def GetMorceaux(album,leficher):
Morceaux =[]
for ligne in lines:
pass
return Morceaux
#Charge les artistes dans une liste nommée LA à partir d'un fichier , puis retounre la liste
def loadArtistes(lefichier):
lesmorceaux = fromfiletoliste(lefichier)
LA =[]
for line in lesmorceaux:
tampon = line.split(';')
if not(TestDoublons(LA,tampon[0])):
LA.append(tampon[0])
return LA
#Retourne le fichier passe en argument comme une liste nommée lines
def fromfiletoliste(Unfichier):
file = open(Unfichier, "r",encoding="utf8")
lines = file.readlines()
file.close()
return lines
#!/usr/bin/python3
# * coding: UTF8 *
# -*- coding: UTF-8 -*-
import cgitb
#https://docs.python.org/2/library/cgi.html
import cgi,os,sys
#pour afficher les erreurs
cgitb.enable()
#pour l'instant, on affiche du html , mais plus tard ...
print ("Content-Type: text/html ;charset=utf-8\r\n\r\n")
#on récupère le formulaire ou les données
form = cgi.FieldStorage()
#On importe notre bibliothèque
from fonctions import *
#notre dictionnaire d'action est pour l'instant vide, mais il existe !
choix = {}
#en fonction des choix de l'utilisateur, toutes les donnéees ne seront pas disposnible , par précaution on va compléter
#le dictionnaire avec des valeurs "vides"
choix["action"]='vide'
choix["artiste"]='vide'
#choix.append('action':"vide")
#en cgi, les données sont passées par un formulaire: méthodes post ou get , ou directement par une url : méthode get
# #on récupère les données
form = cgi.FieldStorage()
#Les lignes suivantes, permettent de "récupérer " les données éventuellement envoyées
if form.getvalue('action'):
choix['action'] = form['action'].value
#pour l'intant le fichier ne change pas
choix['fichier']="../data/listeok.csv"
if form.getvalue('artiste'):
choix['artiste'] = form['artiste'].value
if form.getvalue('album'):
choix['album'] = form['album'].value
if form.getvalue('morceau'):
choix['morceau'] = form['morceau'].value
"""
if choix['action'] == 'voirArtistes':
lesArtistes = loadArtistes(choix['fichier'])
for i in lesArtistes :
print(i+"<br />")
if choix['action'] == 'voirAlbums':
lesAlbums = loadArtistes(choix['fichier'],choix['fichier'])
for i in lesAlbums:
print(i)
if choix['action'] == 'voirMorceaux':
LesAlbums = GetAlbums(choix['album'],choix['fichier'])
if choix['action'] == 'morceaux':
LesMorceaux = GetMorceaux(choix['morceau'],choix['fichier'])
"""
