Lors de la navigation sur le Web, les internautes interagissent avec leur machine par le biais des pages Web.
L’Interface Homme-Machine (IHM) repose sur la gestion d’événements associés à des éléments graphiques munis de méthodes algorithmiques.
On parle de pages Web dynamique lorsque certaines de ces méthodes algorithmiques sont exécutées sur un serveur pour produire un résultat dans le navigateur coté client...
Lire la page Modèle client/serveur proposée par David ROCHE puis répondre aux questions suivantes :
Lorsque vous saisissez l'adresse http://jupyterhub.ecmorlaix.fr:8093 dans Safari sur votre tablette iPad, indiquer qui alors est le client et qui est le serveur ?
Si vous faites une publication locale de votre site web sur votre iPad, depuis l'application iSH Shell (ou a-Shell mini) en saisissant :
python3 -m http.server # à saisir depuis le dossier clone
indiquer qui est le client et qui est le serveur lorsque dans le navigateur de votre iPad, vous entrez l'URL : http://127.0.0.1:8000
?
indiquer qui est le client et qui est le serveur lorsque depuis un navigateur d'une autre machine, vous entrez l'URL : http://<IP_de_votre_iPad>:8000
?
Lire la page Protocole HTTP proposée par David ROCHE puis répondre aux questions suivantes :
...
...
...
...
Flask est un micro-framework Python, un module qui va nous permettre, en seulement quelques lignes de code, de créer un serveur HTTP en Python.
Dans un premier temps nous utiliserons Glitch pour éditer et héberger nos serveurs Flask.
Remixer le projet https://glitch.com/~glitch-flask-python3 et renommer le avec votre prénom au format prenom-1nsi-ecmorlaix-flask-ex0
.
Tester en cliquant sur le bouton Show
le bon fonctionnement de votre serveur Web puis copier/coller un lien vers votre projet dans le code Python de la cellule suivante pour l'intégrer dans ce notebook :
%%HTML
<center>
<iframe src="..." width=70% height="500" ></iframe>
</center>
Observer les fichiers contenus dans ce projet :
README.md
décrit en markdown l'objet du projet ;
glitch.json
donne les instructions à la machine virtuelle (Container) mise à disposition par Glitch pour la configurer et exécuter le fichierserveur.py
;
requirements.txt
indique les modules Python à installer sur la VM ;
serveur.py
contient le code Python de notre serveur HTTP.
Observer plus particulièrement le contenu de ce dernier fichier :
from flask import Flask
permet d'importer le module Flask ;
app = Flask(__name__)
crée un objet Flask nommé app ;
"@app.route("/")"
ceci est un décorateur, celà signifie que la fonction
hello()
qui suit ce décorateur sera appelée dans le cas où le serveur web recevra une requête HTTP avec une URL correspondant à la racine du site (/
)
def hello():
return "<h1>Demat d'an holl, ... ;<br><br>Kenavo !</h1>"
```
A l'appel de la fonction
hello()
, le serveur renvoie vers le client une page HTML contenant la chaine de caractères"<h1>Demat d'an holl, ... ;<br><br>Kenavo !</h1>"
.
app.run()
cette instruction lance le serveur Flask
Modifier le contenu HTML renvoyé par votre serveur Web (soyez créatif !)...
serveur.py
pour ajouter une route telle que :@app.route('/autre')
def autre():
return "<h1>Mon autre page Web</h1>"
Show
et en tapant l'URL /autre
dans la barre d'adresse...Modifier le contenu HTML renvoyé par votre serveur Web pour ajouter des hyperliens permettant de naviguer d'une page à l'autre dans votre site Web...
Ajouter un lien vers une route non définie...
Partager votre site avec d'autres élèves puis, dans Glitch, cliquer sur le bouton Tools
puis sur le bouton Logs
pour visualiser les requètes successives que reçoit votre serveur... Répondre alors aux questions suivantes :
...
...
...
...
Écrire tout le code HTML qui devra être renvoyé au client dans le programme Python n'est pas très pratique, Flask propose une autre solution bien plus satisfaisante : les templates...
Remixer votre précédent projet et renommer le avec votre prénom au format prenom-1nsi-ecmorlaix-flask-ex1
.
Créer un répertoire templates
contenant un fichier index.html
:
Pour le faire en ligne de commande, cliquer sur le bouton
Tools
, puis sur le boutonLogs
, puis sur le boutonConsole
, et enfin saisir :
$ mkdir templates
$ cd templates
$ touch index.html
$ refresh
Il faut systématiquement finir par une commande
refresh
pour que les modifications effectuées enConsole
soient synchronisées dans l'éditeur graphique.
index.html
:<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Accueil</title>
</head>
<body>
<h1>Mon super site</h1>
</body>
</html>
serveur.py
:from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index() :
return render_template("index.html")
app.run()
Show
le bon fonctionnement de votre serveur Web puis copier/coller un lien vers votre projet dans le code Python de la cellule suivante pour l'intégrer dans ce notebook :%%HTML
<center>
<iframe src="..." width=70% height="500" ></iframe>
</center>
Le serveur renvoie maintenant au client la page HTML correspondant au fichier "index.html" qui a été créé dans le répertoire "templates". Attention, les fichiers HTML devront systématiquement se trouver dans un répertoire nommé "templates".
Pour l'instant notre site est statique : la page reste identique, quelles que soient les actions des visiteurs.
Flask permet de créer des pages dynamiques :
serveur.py
tel que :from flask import Flask, render_template
import datetime
app = Flask(__name__)
@app.route('/')
def index():
date = datetime.datetime.now()
h = date.hour
m = date.minute
s = date.second
return render_template("index.html", heure = h, minute = m, seconde = s)
app.run()
import datetime
permet d'importer le module datetime ;
date = datetime.datetime.now()
récupère la date et l'heure courante dans date ;
`h = date.hour
m = date.minute s = date.second `
Après l'exécution des 3 lignes ci-dessus, les variables h, m et s contiennent l'heure courante.
render_template("index.html", heure = h, minute = m, seconde = s)
La fonction
render_template
contient 3 paramètres de plus par rapport à l'exemple précédent : le paramètre "heure", le paramètre "minute" et le paramètre "seconde", nous allons retrouver ces 3 paramètres dans le fichier HTML.
index.html
tel que :<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Accueil</title>
</head>
<body>
<h1>Mon super site</h1>
<hr>
<p> Il est {{heure}} h {{minute}} min et {{seconde}} sec</p>
<hr>
</body>
</html>
Nous avons bien une page dynamique, puisqu'à chaque fois que vous actualisez la page dans votre navigateur, l'heure courante du serveur s'affiche : à chaque fois que vous actualisez la page, vous effectuez une nouvelle requête et en réponse à cette requête, le serveur envoie une nouvelle page HTML (Vérifier les requètes dans
Logs
)
Attention, il est bien important de comprendre que la page HTML envoyée par le serveur au client ne contient plus les paramètres {{heure}}, {{minute}} et {{seconde}}. Au moment de créer la page, le serveur remplace ces paramètres par les valeurs passées en paramètres de la fonction
render_template
(Vérifier en affichant le code source de la page (F12)).
Le fichier
index.html
ne contient donc pas du HTML (même si cela ressemble beaucoup à du HTML), car les paramètres {{heure}}, {{minute}} et {{seconde}} n'existent pas en HTML. Le fichierindex.html
contient en fait un langage de template nommé Jinja. Jinja ressemble beaucoup au HTML, mais il rajoute beaucoup de fonctionnalités par rapport au HTML (notamment les paramètres entourés d'une double accolade comme {{heure}}). Si vous utilisez Jinja seul (sans un framework comme Flask), les paramètres ne seront pas remplacés et votre navigateur affichera "Il est {{heure}} h {{minute}} min et {{seconde}} sec".
%%HTML
<center>
<iframe src="..." width=70% height="500" ></iframe>
</center>
Pour intégrer des fonctionnalités statiques (CSS et JavaScript) à votre projet il faut placer vos fichiers
style.css
etscript.js
dans un nouveau dossier nomméstatic
.Par conséquence, les liens d'accès à ces ressources CSS et JavaScript doivent être modifiés dans le fichier
index.html
du dossiertemplates
Si les noms de répertoire
templates
etstatic
ne vous conviennent pas vous pouvez les renommer à votre guise, par exempleviews
etpublic
mais il faut les déclarer dans l'instruction de création de l'objet Flaskapp
tel queapp = Flask(__name__, static_folder='public', template_folder='views')
Remixer votre précédent projet et renommer le avec votre prénom au format prenom-1nsi-ecmorlaix-flask-ex2-post
.
Modifier le fichier index.html
avec votre prénom tel que :
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Mon formulaire</title>
</head>
<body>
<form action="https://prenom-1nsi-ecmorlaix-flask-ex2-post.glitch.me/resultat" method="post">
<label>Nom</label> : <input type="text" name="nom" />
<label>Prénom</label> : <input type="text" name="prenom" />
<input type="submit" value="Envoyer" />
</form>
</body>
</html>
resultat.html
dans le dossier templates
:<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Résultat</title>
</head>
<body>
<h3>Bonjour {{prenom}} {{nom}}, j'espère que vous allez bien.</h3>
</body>
</html>
serveur.py
tel que :from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/resultat',methods = ['POST'])
def resultat():
result = request.form
n = result['nom']
p = result['prenom']
return render_template("resultat.html", nom=n, prenom=p)
app.run()
Show
le fonctionnement de votre serveur Web, vérifier les requètes dans Logs
, puis copier/coller un lien vers votre projet dans le code Python de la cellule suivante pour l'intégrer dans ce notebook :%%HTML
<center>
<iframe src="..." width=70% height="500" ></iframe>
</center>
Si vous saisissez, par exemple, HOPPER
et Grace
dans les champs Nom
et Prénom
du formulaire, qu'obtennez-vous après avoir appuyé sur le bouton Envoyer
?
...
Nous effectuons une requête HTTP avec l'URL /
, le serveur génère une page web à partir du fichier index.html
, cette page, qui contient un formulaire (balise <form action="https://prenom-1nsi-ecmorlaix-flask-ex2-post.glitch.me/resultat" method="post">
) est envoyée vers le client. On remarque 2 attributs dans cette balise form : action="https://prenom-1nsi-ecmorlaix-flask-ex2-post.glitch.me/resultat"
et method="post"
. Ces 2 attributs indiquent que le client devra effectuer une requête de type POST (la méthode POST a déjà été vue dans la partie consacrée au protocole HTTP) dès que l'utilisateur appuiera sur le bouton Envoyer
. Cette requête POST sera envoyée à l'URL https://prenom-1nsi-ecmorlaix-flask-ex2-post.glitch.me/resultat
(voir l'attribut action
). Les données saisies dans le formulaire seront envoyées au serveur par l'intermédiaire de cette requête.
Vous avez sans doute remarqué que la méthode à employer pour effectuer la requête HTTP n'est pas précisée dans le "@app.route('/')". Si rien n'est précisé, par défaut, c'est la méthode GET qui est utilisée.
Intéressons-nous à la fonction resultat()
, puisque c'est cette fonction qui sera exécutée côté serveur pour traiter la requête POST :
def resultat():
result = request.form
n = result['nom']
p = result['prenom']
return render_template("resultat.html", nom=n, prenom=p)
request.form
est un dictionnaire Python qui a pour clés les attributs name
des balises input
du formulaire (dans notre cas les clés sont donc nom
et prenom
) et comme valeurs ce qui a été saisi par l'utilisateur. Si l'utilisateur saisit HOPPER
et Grace
, le dictionnaire request.form
sera :
{'nom':'HOPPER', 'prenom':'Grace'}
Le template resultat.html
utilise des paramètres nom
et prenom
.
En réponse à la requête POST, le serveur renvoie une page HTML créée à partir du template resultat.html
et des paramètres nom
et prenom
. Si l'utilisateur a saisi HOPPER
et Grace
, le navigateur affichera :
Pour gérer le formulaire, il est possible d'utiliser une méthode HTTP GET à la place de la méthode POST :
Remixer votre précédent projet et renommer le avec votre prénom au format prenom-1nsi-ecmorlaix-flask-ex2-get
.
Modifier le fichier index.html
avec votre prénom tel que :
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Le formulaire</title>
</head>
<body>
<form action="https://prenom-1nsi-ecmorlaix-flask-ex2-get.glitch.me/resultat" method="get">
<label>Nom</label> : <input type="text" name="nom" />
<label>Prénom</label> : <input type="text" name="prenom" />
<input type="submit" value="Envoyer" />
</form>
</body>
</html>
serveur.py
tel que :from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/resultat',methods = ['GET'])
def resultat():
result = request.args
n = result['nom']
p = result['prenom']
return render_template("resultat.html", nom=n, prenom=p)
app.run()
Dans index.html
, la méthode POST a été remplacée par la méthode GET. Dans le fichier serveur.py
nous avons aussi remplacé POST par GET, et on utilise request.args
à la place de request.form
.
Show
le fonctionnement de votre serveur Web, vérifier les requètes dans Logs
, puis copier/coller un lien vers votre projet dans le code Python de la cellule suivante pour l'intégrer dans ce notebook :%%HTML
<center>
<iframe src="..." width=70% height="500" ></iframe>
</center>
Grace
pour le prénom et HOPPER
pour le nom puis valider en cliquant sur le bouton Envoyer
. Observer alors attentivement la barre d'adresse du navigateur. Que remarquez-vous de particulier ?...
Vous avez dû remarquer que cette fois-ci, les informations du formulaire sont transmises au serveur par l'intermédiaire de l'URL : https://prenom-1nsi-ecmorlaix-flask-ex2-get.glitch.me/resultat?nom=HOPPER&prenom=Grace
Dans le cas de l'utilisation d'une méthode POST les données issues d'un formulaire sont envoyées au serveur sans être directement visibles, alors que dans le cas de l'utilisation d'une méthode GET, les données sont visibles (et accessibles) puisqu'elles sont envoyées par l'intermédiaire de l'URL. De plus, les données envoyées par l'intermédiaire d'une méthode "GET" peuvent être modifiées directement dans l'URL...
...
Contenus | Capacités attendues | Commentaires |
---|---|---|
Interaction clientserveur. Requêtes HTTP, réponses du serveur |
Distinguer ce qui est exécuté sur le client ou sur le serveur et dans quel ordre. Distinguer ce qui est mémorisé dans le client et retransmis au serveur. Reconnaître quand et pourquoi la transmission est chiffrée. |
Il s’agit de faire le lien avec ce qui a été vu en classe de seconde et d’expliquer comment on peut passer des paramètres à un site grâce au protocole HTTP. |
Formulaire d’une page Web | Analyser le fonctionnement d’un formulaire simple. Distinguer les transmissions de paramètres par les requêtes POST ou GET. |
Discuter les deux types de requêtes selon le type des valeurs à transmettre et/ou leur confidentialité. |
Ce document, basé sur le travail de David ROCHE, est mis à disposition selon les termes de la Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International.
Pour toute question, suggestion ou commentaire : eric.madec@ecmorlaix.fr