Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site
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 !
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.
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.
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
Cinq champs : id, nom_espece, code, photo, e_descripton. Son contenu :
Une espèce appartient à un taxon (clade) et un seul.
les colonnes "especes.code" & "taxons.code" indiquent le code du taxon.
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
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.
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.
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".
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.
@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.
Ce fichier ressemble beaucoup à "liste.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.
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% ; }
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.
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.
@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.
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'.
@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.
On parvient à afficher une image par fiche en précisant dans l'attribut "filename" le nom de l'image (contenu du champ "espces.photo".
Là aussi il y a deux étapes.
@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.
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.
Pour cette deuxième étape uniquement une route supplémentaire dans le script.
@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.
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.
Le rendu après avoir saisi "localhost:5000" dans la barre d'URL et avoir sélectionner "décapodes" dans la liste déroulante :
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 ...
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"