Faire des sondages avec flask et ethercalc

Installer flask

Note Tout ce tutorial est basé sur python3... Suivant votre machine, vous devrez utiliser la commande python3 au lieu de python. Pour plus d'informations sur le processus d'installation (notamment l'installation sous Windows), voir la section correspondante de la documentation flask.

~$ mkdir polls
~$ cd polls
~/polls$ python -m venv venv
~/polls$ source venv/bin/activate
(venv) ~$ pip install flask

Hello World avec Flask

Créez un fichier polls.py avec un programme Flask minimal:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello World!'

C'est le moment de tester:

(venv) ~/polls$ export FLASK_APP='polls.py'
(venv) ~/polls$ export FLASK_DEBUG=1
(venv) ~/polls$ flask run

Ou, en plus ramassé:

(venv) ~/polls$ FLASK_APP=polls.py FLASK_DEBUG=1 flask run

S'il n'y a pas d'erreur, rendez-vous sur http://localhost:5000/ où vous devriez être accueilli par un sympathique Hello World!

Simplifier la reprise ou le déployement du projet

(venv) ~/polls$ pip freeze > requirements.txt
(venv) ~/polls$ cat requirements.txt
click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
Werkzeug==1.0.1

Dorénavant, il suffira de faire un pip install -r requirements.txt pour reconstituer l'ensemble des bibliothèques dans les bonnes versions! Ce fichier devra bien entendu être versionné avec votre code.

Attention! Ne pas oublier de mettre ce fichier à jour à chaque nouvelle installation ou mise à jour d'une bibliothèque!

Créer une feuille ethercalc...

Rendez-vous sur https://ethercalc.openstack.org/ et créez une nouvelle feuille.

  1. Prenez note de l'ID généré car nous en aurons besoin par la suite (et c'est la seule manière de retrouver votre feuille...).
  2. Dans la cellule A1, entrez le titre de votre sondage.
  3. Dans les cellules B2, C2, E2, ... entrez les options de votre sondage. Pour plus de clareté, vous pouvez noter "Nom" en A2 (le nom des personnes ayant voté s'inscrira dans cette colonne).

Exemple de google doc

Nous allons maintenant changer la page d'accueil: remplacez la méthode hello() par

@app.route('/')
def poll_list():
    # Adaptez l'ID à la feuille que vous avez créée ci-dessus!
    return render_template('home.html', poll_id='zxya1mcjhwkv')

Pour que cela fonctionne, il faudra

Testez: http://localhost:5000/ devrait maintenant vous donner un lien vers votre sondage... mais naturellement un lien brisé!

On va donc corriger ça. D'abord on se donne un moyen de récupérer les données du sondage:

def get_poll_as_csv(id):

    url = f'https://ethercalc.openstack.org/_/{id}/csv'
    answer = urlopen(url)
    content =  answer.read().decode(answer.headers.get_content_charset()).splitlines()
    reader = csv.reader(content)
    return list(reader)

(sans oublier d'ajouter les imports correspondants en haut du fichier:

from urllib.request import urlopen
import csv

)

Ensuite on définit la route:

@app.route("/<id>")
def display_poll(id):

    sheet = get_poll_as_csv(id)

    # First line has title
    title = sheet.pop(0)[0]

    # Second line is dummy value, then options:
    options = sheet.pop(0)[1:]

    return render_template("poll.html", **locals())

... et enfin le template poll.html

<h1>{{title}}</h1>

<ul>
    {% for o in options %}
        <li>{{o}}</li>
    {% endfor %}
</ul>

Vous devriez maintenant pouvoir aller sur la page du sondage et voir les options possibles.

Vers une mise en place du vote...

Nous avons réussi à aller chercher des informations dans un tableur, il nous reste à les modifier...

Juste sous le <h1> de poll.html, ajoutez

<form action="" method="post">
    <label for="id_who">Your Name</label>
    <input type="text" name="who" id="id_who" />
    <input type="submit" class="button" value="Vote!"/>
</form>

On se donne le moyen d'ajouter des données à notre feuille via l'API d'ethercalc:

def add_row_to_poll(id, data):
    url = f'https://ethercalc.openstack.org/_/{id}'
    headers = {
        'Content-Type': 'text/csv'
    }
    new_row = ','.join(f'"{s}"' for s in data)+','
    request = Request(url,
                      headers=headers,
                      data=new_row.encode('utf-8'))
    urlopen(request)

On complète l'import d'urllib:

from urllib.request import urlopen, Request

On modifie ensuite la déclaration de display_poll:

@app.route("/<id>", methods=['GET'])
def display_poll(id):
    [...]

Et enfin, on ajoute

@app.route('/<id>', methods=['POST'])
def vote(id):

    voter = request.form['who']
    add_row_to_poll(id, [voter])

    return redirect(url_for('display_poll', id=id))

(sans oublier d'importer request, redirect et url_for du package flask!)

On devrait maintenant pouvoir "voter": le nom du participant est ajouté au tableur... mais le participant n'a pas encore l'occasion de donner son avis!

À vous de jouer!

En vous aidant de la documentation de flask, de celle de Jinja2, et au besoin de la doc de l'API d'ethercalc effectuez les tâches suivantes:

Et si vous avez le temps...

Ajoutez quelques améliorations parmi les idées ci-dessous:

Pour aller plus loin...