Accueil

Traduction

Tutoriel Python - sommaire

Tutoriel Python - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Une application web développée avec Flask

Dans ce chapître nous allons réaliser une application web avec Flask. J'emploie le terme "application" puisqu'il aura utilisation d'une base de données SQLite. Donc les pages web seront dynamiques !

Travaux préalables

La structure du projet sera identique à celle de "mollusques" (voir chapitre précédent).

Créer à la racine de C: un nouveau dossier et nommez le "faune_gerer".
Au sein de ce répertoire, créez deux dossiers : "static" & "templates".
Dans le répertoire "static" créez deux sous-dossiers : "css" et "images"

Pour gagner du temps nous allons justement réutiliser des fichiers du projet précédent.
Ainsi la feuille de style externe sera pratiquement identique.

La BD "faune.db"

Vous récupérerez cette base en téléchargeant un fichier zip ; voir fin du chapitre.

Cette base est très proche de la base "animaux.db" utilisée dans les chapitres sur SQLite.
Elle comprend deux tables.

La table "taxons"

Deux colonnes : code, nom_taxon. Son contenu :


hydr	hydraires	
medu	méduses	
acti	actinies	
cten	cténaires	
plat	vers plats	
anne	annélidés	
biva	bivalves	
chit	chitons	
gast	gastéropodes	
ceph	céphalopodes	
deca	décapodes	
amph	amphipodes	
cart	poissons cartilagineux	
osse	poissons osseux	
agna	agnathes	

La table "especes"

Cinq champs : id, nom_espece, code, photo, e_descripton. Son contenu :

Relation entre les tables

Une espèce appartient à un taxon (clade) et un seul.
les colonnes "especes.code" & "taxons.code" indiquent le code du taxon.

Une vue

Cette vue (requête sélection sauvegardée) associe à chaque ligne de "especes" une ligne de "taxons".

CREATE VIEW "vue3" AS SELECT nom_espece, taxons.code as code, nom_taxon, photo 
FROM especes 
INNER JOIN taxons 
ON especes.code = taxons.code

Conseils

Si vous ne savez plus trop ce qu'est le SGBDR SQLite et comment manipuler une telle BD en Python, je vous invite à revoir les chapitres 17 & 18.

Les fonctionnalités faciles à programmer

Commençons par des traitements simples : afficher dans un template le résultat d'une requête sélection ou d'une vue.
Il faut donc une route qui produit des données (via une requête sélection) et ensuite affiche un template en lui injectant ces données.

Le template "liste.htm"

Il sera utilisé pour afficher la liste des espèces par ordre alphabétique OU la liste des espèces par taxon.

Le code du template :

Notez l'inclusion du code du fichier "commun.htm".

Extraits du script "application.py"

from flask import Flask, render_template, request, url_for
import sqlite3

app = Flask(__name__)
	
@app.route('/liste_alpha')
def liste_alpha():
	connexion = sqlite3.connect("faune.db")
	curseur = connexion.cursor()	
	curseur.execute("select * from vue3 order by nom_espece,code")
	resultat = curseur.fetchall()
	legende ="liste des espèces par ordre alphabétique"
	return render_template("liste.htm", lignes = resultat,titre=legende)
	connexion.close()
	
@app.route('/liste_taxon')
def liste_taxon():
	connexion = sqlite3.connect("faune.db")
	curseur = connexion.cursor()	
	curseur.execute("select * from vue3  order by code, nom_espece ")
	resultat = curseur.fetchall()
	legende ="liste des espèces par taxon"
	return render_template("liste.htm", lignes = resultat, titre = legende)
	connexion.close()

if __name__ == "__main__":
    app.run()

Il faut importer le module "sqlite3" puisque nous allons manipuler un BD de ce type.

Liste des taxons

Nouvelle route dans "application.py"

@app.route('/taxons')
def taxons():
	connexion = sqlite3.connect("faune.db")
	curseur = connexion.cursor()
	curseur.execute("select code, nom_taxon from taxons order by code")
	resultat = curseur.fetchall()
	return render_template("taxons.htm", lignes = resultat)
	connexion.close()

Le code de cette route est très proche des deux précédentes.

Le template "taxons"

Ce fichier ressemble beaucoup à "liste.htm".

Template "commun.htm", feuille de style "style.css" , images

Le template "commun.htm"

Tous les autres templates héritent de "commun.htm".

Dans la partie HEAD lien vers la feuille de style externe (preque la même que pour le projet "mollusques" (voir chapitre précédent).

Toutes les pages ont un contenu identique pour des divisions HEADER & NAV de BODY. Par contre le contenu diffère entre les pages pour ce qui concerne la division SECTION.

La feuille de style "style.css"

Concernant le fichier .css j'ai rajouté des styles pour les balises H3, les items de liste à puces et les éléments de formulaire.
Comme pour la version précédente les pages sont "responsives" et il y a un effet visuel pour les images sur survol.

Rajouts dans la feuille de style par rapport à la version dans le projet "mollusques" :

	h3 {font-size : 1.2em; background : olive ; margin : 10px ;}
	ul,ol {margin : 10 px ; color : navy; list-style : inside;  }
	input, label, button {height : 30px ; margin : 10px 1% ; }

Le sous-dossier "images"

Pour chaque espèce il doit y avoir une photo. Toutes les images sont au format JPG.
Le nom de la photo par rapport au nom de l'espèce doit être logique.
Exemple : si le nom de l'espèce est "crevette grise" le nom de la photo correspondante est "crevette_grise.jpg"
Exemple 2 : si le nom de l'espèce est "araignée de mer" le nom de la photo ad hoc est : "araignee_mer.jpg"
Donc jamais de lettres accentuées, ni de majuscules, ni d'espaces dans les noms des photos.

Liste des images dans ce dossier

Notez que toutes les images ont le même type (jpg), pas de lettres accentuées, par de majuscules, pas d'espaces.
Mais surtout le nom de la photo est logique par rapport au nom de l'espèce.

Sélection d'un taxon et affichage des fiches espèce correspondantes

Première étape

La nouvelle route

@app.route('/')
def accueil():
	connexion = sqlite3.connect("faune.db")
	curseur = connexion.cursor()	
	curseur.execute("select code, nom_taxon from taxons order by code")
	resultat = curseur.fetchall()
	connexion.close()
	return render_template("index.htm", lignes = resultat)    

Il s'agit de la route qui s'exécute automatiquement dès que l'on a tapé "localhost:5000" dans la barre d'url.

Le template "index.htm"

Les données produites par la requête sélection permettent de produire une liste déroulante dans un formulaire.
La valeur de "choix" est adressée à la route 'fiches'.

Deuxième étape : afficher les fiches espèces du taxon

Nouvelle route dans le script : /fiches

@app.route('/fiches', methods =["POST"])
def fiches():
	connexion = sqlite3.connect("faune.db")
	connexion.row_factory =sqlite3.Row
	curseur = connexion.cursor()
	choix = request.form['choix']
	sql = \
	"select nom_espece, code, photo, e_description from especes where code =?"
	curseur.execute(sql,(choix,))
	resultat = curseur.fetchall()
	return render_template("fiches.htm", lignes = resultat)
	connexion.close()	

Exécution d'une requête paramétrée dont l'argument est "choix".
Affichage du template "fiches.htm" qui récupère les données produites par la requête.

Template qui affiche les données produites par la route '/fiches' : "fiches.htm"

On parvient à afficher une image par fiche en précisant dans l'attribut "filename" le nom de l'image (contenu du champ "espces.photo".

Ajout d'une espèce

Là aussi il y a deux étapes.

Première étape : sélectionner un taxon.

Nouvelle route dans "application.py"

@app.route('/nouvelle_espece')
def nouvelle_espece(): 
	connexion = sqlite3.connect("faune.db")
	curseur = connexion.cursor()
	sql = "select code, nom_taxon from taxons order by code"
	curseur.execute(sql)
	resultat = curseur.fetchall()
	return render_template("ajout_espece.htm",lignes = resultat)
	connexion.close()

Le résultat de la requête est transmis au template "ajout_espece" pour construire une liste déroulante de formulaire.

Le template "ajout_espece.htm"

Pensez à la structure de la table "especes" : id, nom_espece, code, photo.

Les soumissions sont transmises à la route "ajout_especes" (voir ci-dessous).

Le template comprend un formulaire pour saisir les données dont une liste pour saisir le code.

Deuxième étape : insertion d'une ligne dans la table "especes".

Pour cette deuxième étape uniquement une route supplémentaire dans le script.

Nouvelle route dans "application.py"

@app.route('/ajout_espece',methods = ['POST'])
def ajout_espece():
	nom = request.form['nom']
	code = request.form['code']
	photo = request.form['photo']
	description = request.form['description']
	connexion = sqlite3.connect("faune.db")
	connexion.row_factory =sqlite3.Row
	curseur = connexion.cursor()
	sql ="INSERT INTO  especes \
	(nom_espece, code, photo, e_description) VALUES (?,?,?,?)"
	curseur.execute(sql,(nom,code,photo,description))
	connexion.commit()		
	connexion.close()

Cette route récupère les données transmises par le formulaire de "ajout_espece.htm" .
Construction d'une requête INSERT puis exécution de cette requête.

Conclusion

Oui, je suis d'accord c'est un peu plus compliqué qu'un site statique tel que celui traité dans le chapitre précedent.
Mais le gros avantage est que le contenu des pages évolue à chaque fois que la BD est modifiée. On parle de site dynamique.

Aperçu dans le navigateur

Le rendu après avoir saisi "localhost:5000" dans la barre d'URL et avoir sélectionner "décapodes" dans la liste déroulante :

application web avec Flask

Un projet inachevé

Il manque une fonctionnalité : ajout d'enregistrements dans la table "taxons".
En vous inspirant de la fonctionnalité "ajout d'espèce" vous devriez être capable de la faire ...

Récupération du projet

Vous pouvez télécharger un fichier zip correspondant aux images et au code CSS et la base de données.
Par contre vous devez écrire les templates et le script. Ce sera l'occasion de vous familiariser avec la syntaxe des templates.

Le sous-dossier "static" (images & css) du projet à récupérer
La base de données "faune.db"