Tu deviendras web designer, mon fils

Magazine
Marque
GNU/Linux Magazine
Numéro
167
Mois de parution
janvier 2014
Spécialité(s)


Résumé
Nous avons récemment [GLMF 166] vu comment créer facilement une application Web avec Flask. S'il s'avère relativement simple, muni de quelques connaissances python, de produire un Web Service fonctionnel, réaliser une application moderne, responsive, mais surtout jolie, peut se transformer en véritable cauchemar pour le quidam dont les connaissances en web design se limitent au strict minimum .

Body

Fort heureusement, il existe de nos jours de nombreuses béquilles qui aident les déficients de l'ergonomie que nous sommes et, parmi elles, le module python WTForms et le framework Bootstrap qui nous permettrons respectivement de générer des formulaires propres et de produire une interface de belle facture.

1. Au début était le moche

Nous démarrerons notre expérience par la création d'une application Flask basique: Un formulaire de trois champs dont le résultat sera inscrit dans un fichier plat après validation.

Le code Flask est le suivant :

$ cat basic.py
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route(‘/’, methods=[‘GET’, ‘POST’])
def basicform():
if request.method == ‘POST’:
with open(‘/tmp/test.txt’, ‘w’) as f:
for k in request.form:
f.write(‘{0}: {1}\n’.format(k, request.form[k]))
return render_template(‘basic.html’)
if __name__ == ‘__main__’:
app.run(debug=True)

Et le template associé :

$ cat templates/basic.html
<!doctype html>
<title>Bienvenue, visiteur du futur !</title>
<div class="content">
<h2>Identification</h2>
<hr>

<form method="POST" action="/">
<label>Utilisateur</label><br />
<input type="text" name="user" id="user"><br />
<label>Mot de passe</label><br />
<input type="password" name="passwd" id="passwd"><br />
<select name="active" id="active">
<option value="no">Non</option>
<option value="yes">Oui</option>
</select><br />
<input type="submit" name="action" value="register">
</form>
</div>

Sans surprise, ce duo produit l'interface suivante :

moche

Fig. 1 : Moche

C'est laid, c'est sur, mais surtout, que de caractères tapés pour un résultat aussi sommaire… Alors que nous utilisons un framework pour générer notre GUI, n'y a-t-il pas de moyen plus efficace pour produire ces sempiternels formulaires ?

2. C'est quoi ce !@#!@#

WTForms est un module python permettant de grandement factoriser la création de formulaires. En couplant la puissance du moteur de template Jinja2, nativement intégré à Flask et la souplesse de WTForms, il devient simplissime de générer des formulaires avec un minimum d'efforts.

Il suffit pour cela d'importer le type de champs souhaité, puis de faire hériter son formulaire de l'objet Form et d'y lister les différents types de données. Plus fort, WTForms permet sans beaucoup plus de travail d'intégrer des validateurs, afin de vérifier que le contenu des champs correspond bien à l'entrée souhaitée; par exemple, en vérifiant le nombre de caractères ou encore la valeur maximale d'une valeur.

Après avoir préalablement installé le module WTForms, par exemple via pip, nous créons un fichier forms.py contenant les champs du formulaire précédemment créé à la main :

from wtforms import Form, TextField, SelectField, SubmitField, PasswordField,
validators
class BasicForm(Form):
user = TextField(u’Utilisateur’, [validators.Length(min=4, max=20)])
passwd = PasswordField(u’Mot de passe’, [validators.Length(min=8, max=32)])
active = SelectField(u’Actif’, choices = [(‘yes’, ‘Yes’), (‘no’, ‘No’)])
action = SubmitField(u’Register’)

On importe cette classe dans notre fichier basic.py et instancions un objet form que l'on passera en paramètre à notre template, capable de l'utiliser via Jinja :

from flask import Flask, request, render_template, url_for
from forms import BasicForm
app = Flask(__name__)
@app.route(‘/’, methods=[‘GET’, ‘POST’])
def basicform():
form = BasicForm(request.form)
if request.method == ‘POST’ and form.validate():
with open(‘/tmp/test.txt’, ‘w’) as f:
for k in request.form:
f.write(‘{0}: {1}\n’.format(k, request.form[k]))
return render_template(‘basic.html’, form=form)
if __name__ == ‘__main__’:
app.run(debug=True)

On notera qu'on passe la requète en paramètre à la classe BasicForm, ceci afin de contrôler la validité des champs postés via notre formulaire.

Apprécions maintenant la puissance du duo Jinja/WTForms. Voici notre précédent template, réduit à un plus simple appareil :

$ cat templates/basic.html
<!doctype html>
<title>Bienvenue, visiteur du futur !</title>
<div class="content">
<h2>Identification</h2>
<hr>
<form method="POST" action="/">
{% for field in form %}
{{ field.label }}
{{ field }}<br />
{% endfor %}
</form>
</div>

Ah oui, ça oui, c'est classe (ah-ah jeu de mots involontaire). Dans ce minuscule template, nous bouclons sur le paramètre form que nous avons passé en paramètre et, pour chaque valeur, on affiche la propriété label, la chaîne de caractères spécifiée en premier paramètre des champs définis dans le fichier forms.py, et le champs lui même. WTForms se charge seul de placer correctement toutes les balises nécessaires et nomme les attributs selon le nom de la variable contenant l'objet à afficher.

moche2

Fig. 2 : Pouah...

3. Et tu nous prends pas pour des jambons des fois ?

Je sais, je sais, c'est toujours moche. Nous y venons.

Bootstrap est un framework libéré en Août 2011 par Twitter simplifiant de façon radicale la stylisation d'un site web. Son utilisation est remarquablement aisée et sa documentation limpide et concrète. Le champs d'action de Bootstrap va des formulaires aux barres de navigation, en passant par les labels et autres tableaux. Une particularité notable de Bootstrap, et l'un des aspects qui en font un projet extrêmement populaire, réside dans sa capacité native à gérer le Responsive Design, ou en termes moins flanbyesques, la capacité d'un site à s'adapter à tout type de périphériques: stations de travail aux écrans sur-dimentionnés, tablettes, smartphones… Cette fonctionnalité repose sur un concept clair et intelligent, Bootstrap découpe la fenêtre du navigateur en une grille de douze colonnes; en ajoutant à vos balises une classe de type col-<type>-<taille>, on sait exactement comment se positionnera l'élément dans la page.

Exemple :

<div class="col-xs-12 col-md-8">.col-xs-12 col-md-8</div>

Ici, pour un périphérique mobile, bénéficiant donc d'une taille réduite (xs pour extra small), on spécifie que l'élément <div> occupera 12 colonnes alors que pour un équipement de taille moyenne (md pour medium), il n'en occupera que 8.

De façon plus générale, la stylisation de tous les éléments d'un site web à l'aide de ce framework s'effectue en ajoutant des classes aux éléments souhaités, on rendra par exemple un bouton beau en lui appliquant les classes btn btn-default pour un design standard ou encore btn btn-primary pour un bouton sur lequel on veut mettre l'emphase.

Dans notre template, on “active” Bootstrap de façon triviale. Après avoir téléchargé l'archive de Bootstrap, on copie les fichiers dist/css/bootstrap.min.css et dist/css/bootstrap-theme.min.css dans le répertoire static de notre projet Flask. Il s'agit ici des versions minifiées, privées des retours à la ligne et espacements inutiles. Nous ne nous occupperons pas, dans cet article, des capacités JavaScript de Bootstrap, aussi nous ne copierons pas le fichier dist/js/bootstrap.min.js.

Voici l'allure de notre template bootstrapé :

<!doctype html>
<html>
<head>
<title>Bienvenue, visiteur du futur !</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel=stylesheet type=text/css href="{{ url_for(‘static’,
filename=’bootstrap.min.css’) }}" media="screen">
<link rel=stylesheet type=text/css href="{{ url_for(‘static’,
filename=’bootstrap-theme.min.css’) }}" media="screen">
</head>
<body>
<div class="content" style="padding: 10px; width: 300px;">
<form method="POST" action="/">
<fieldset>
<legend>Identification</legend>
{% for field in form %}
<div class="form-group">
{% if field.type == ‘SubmitField’ %}
{{ field(class="btn btn-primary") }}
{% else %}
{{ field.label }}
{{ field(class="form-control") }}
{% endif %}
</div>
{% endfor %}
</fieldset>
</form>
</div>
</body>
</html>

L'en-tête de ce template est très largement inspirée de l'exemple proposé sur le site de Bootstrap, que ces derniers recommandent de copier verbatim. La seule modification, outre l'absence de l'inclusion de la section JavaScript, réside dans l'utilisation de la fonction Flask url_for('static'), qui renvoie le répertoire contenant les éléments statiques du projet Flask.

La structure du formulaire est elle aussi dictée par la documentation de Bootstrap, cette simple organisation et l'ajout de la classe form-control aux éléments du formulaire a pour immédiate conséquence le rendu suivant :

beau

Fig. 3 : oooOOOOOoooh

Eh oui, tout ce temps je vous avais caché qu'en fait, je suis un puissant web designer r0x0r.

4. Je vois tes yeux briller

Vous imaginez bien que les possibilités du triptique Flask-WTForms-Bootstrap sont très vastes, pensez qu'en écrivant les macros Jinja adéquates, on peut encore factoriser de façon drastique une application web, si complexe soit-elle. Voici deux exemples de macros que j'utilise dans un projet professionnel articulé autour des composants que nous avons expérimenté :

{% set bs_col = ‘col-sm-8’ %}
{% macro input_text(field) -%}
<div class="form-group {{ bs_col }}">
{{ field.label }}
{% if ‘dsc’ in field.description %}
<small><em>( {{ field.description[‘dsc’] }} )</em></small>
{% endif %}
{{ field(class="form-control", placeholder=field.description[‘ph’]) }}
</div>
{%- endmacro %}
{% macro select(field) -%}
<div class="form-group {{ bs_col }}">
{{ field.label }}
{{ field(class="form-control") }}
</div>
{%- endmacro %}

Il est alors possible d'appeler des macros au sein d'autres templates Jinja grâce à la capacité de ce dernier module à importer des fichiers, tels que son langage originel python.

Pour finir, la courbe d'apprentissage des solutions présentées est relativement courte, essentiellement grâce aux excellentes documentations proposées par ces projets (tous Libres, je le rappelle), profitez donc de ces technologies modernes, pourvues d'un rendu exemplaire, qui ne manqueront certainement pas d'épater la galerie.

Liens

[1]: http://flask.pocoo.org/

[2]: http://fr.wikipedia.org/wiki/Responsive_Web_Design

[3]: http://wtforms.simplecodes.com

[4]: http://getbootstrap.com/

[5]: http://jinja.pocoo.org/




Article rédigé par

Par le(s) même(s) auteur(s)

Des bits comme s'il en pleuvait : une appliance SAN/NAS sous NetBSD

Magazine
Marque
GNU/Linux Magazine
Numéro
181
Mois de parution
avril 2015
Spécialité(s)
Résumé
À Noël, je suis le désespoir de ma famille. En effet, là où d'autres demandent des Blu-ray, de quoi s'habiller en hiver ou encore une nouvelle poêle à frire, moi je demande des composants. Des disques, des cartes, des trucs super pas excitants pour les personnes qui vous les offrent. Cette année, je voulais plus de place sur mon NAS [1], plein de bits pour y coller des documents à haute teneur multimédia.

Les différents BSD

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
74
Mois de parution
septembre 2014
Spécialité(s)
Résumé

« Salut, je voudrais installer *BSD, vous me conseillez quoi ? »Cette phrase, lue et relue des centaines, des milliers de fois, est fondamentalement incorrecte. *BSD n'existe pas. Plus important, lorsque l'on souhaite mettre le pied à l'étrier d'un système BSD, un minimum de contexte est nécessaire, car chacun des héritiers de BSD UNIX suit une philosophie bien définie, et si chacun d'entre eux s'avère éminemment versatile, certains seront plus adaptés et faciles d'accès fonction de l'utilisation souhaitée. Nous allons ici faire connaissance avec les trois systèmes BSD les plus connus, NetBSD, FreeBSD et OpenBSD et évoquer leurs forces et faiblesses afin de guider votre choix de façon la plus objective possible.

NetBSD, le système du futur du subjonctif

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
74
Mois de parution
septembre 2014
Spécialité(s)
Résumé
« The Original UNIX », c'est pour cette punchline que j'avais voté lorsque le groupe chargé du marketing chez NetBSD cherchait une approche différente du classique « of course it runs NetBSD » ; néanmoins, s'il est l'héritier le plus direct des travaux du CSRG [1] et l'un des plus grands défenseurs de la portabilité du code, le projet NetBSD n'est certainement pas un système d'exploitation du passé, loin s'en faut. Bénéficiant des avancées standards d'autres OS, NetBSD dispose en outre d'avantages uniques dont l'administrateur système aguerri saura faire usage. Dans cet article, nous allons monter un serveur web articulé autour de briques modernes, et allons dans notre périple découvrir l'ensemble des éléments nécessaires au déploiement d'un système aussi réactif que respectueux des standards.

Les derniers articles Premiums

Les derniers articles Premium

Game & Watch : utilisons judicieusement la mémoire

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Au terme de l'article précédent [1] concernant la transformation de la console Nintendo Game & Watch en plateforme de développement, nous nous sommes heurtés à un problème : les 128 Ko de flash intégrés au microcontrôleur STM32 sont une ressource précieuse, car en quantité réduite. Mais heureusement pour nous, le STM32H7B0 dispose d'une mémoire vive de taille conséquente (~ 1,2 Mo) et se trouve être connecté à une flash externe QSPI offrant autant d'espace. Pour pouvoir développer des codes plus étoffés, nous devons apprendre à utiliser ces deux ressources.

Raspberry Pi Pico : PIO, DMA et mémoire flash

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Le microcontrôleur RP2040 équipant la Pico est une petite merveille et malgré l'absence de connectivité wifi ou Bluetooth, l'étendue des fonctionnalités intégrées reste très impressionnante. Nous avons abordé le sujet du sous-système PIO dans un précédent article [1], mais celui-ci n'était qu'une découverte de la fonctionnalité. Il est temps à présent de pousser plus loin nos expérimentations en mêlant plusieurs ressources à notre disposition : PIO, DMA et accès à la flash QSPI.

Programmation des PIO de la Raspberry Pi Pico

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

La carte Pico de Raspberry Pi est appréciable à bien des égards. Ses ressources, son prix, ses deux cœurs ARM... Mais ce morceau de silicium qu'est le RP2040 renferme une fonctionnalité unique : des blocs PIO permettant de créer librement des périphériques supplémentaires qu'il s'agisse d'éléments standardisés comme SPI, UART ou i2c, ou des choses totalement exotiques et très spécifiques à un projet ou un environnement donné. Voyons ensemble comment prendre en main cette ressource et explorer le monde fantastique des huit machines à états de la Pico !

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 53 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous