Introduction au moteur SQLlite3

Cet article présente le moteur SQLlite3 et son utilisation en Flask

Home flask

Contexte

Actuellement, notre application utilise une liste Python pour stocker nos contacts. Lorsque le serveur est relancé, les données sont réinitialisés et toutes les modifications effectuées par l'utilisateur sont perdues. En pratique, il est nécessaire d'utiliser un moyen de stockage persistant. Dans cette partie, nous allons utiliser une base de données sqlite. En plus du stockage persistant, le moteur SQLite gèrent également les requêtes SQL.

Le moteur SQLite

Documentation SQLite3: https://www.sqlite.org/index.html

SQLite est une librairie logicielle implémentant un moteur de base de données SQL. Ce moteur est autonome, léger et ne nécessite aucune étape de configuration. Même si ce moteur est léger, il permet toutefois de gérer des bases de données de très grandes tailles (> 140 To). Pour ces raisons, le moteur SQLite est l'un des plus utilisé.

SQLite gère la plupart des requêtes SQL. La requête SELECT permet de rechercher du contenu dans une base de donnée. Sa syntaxe est la suivante

SELECT attribut1, attribut2, ...
FROM table
WHERE attribute1 = valeur

Les requêtes INSERT, UPDATE et DELETE permettent d'ajouter, de modifier ou de supprimer du contenu dans la base de données. Ces requêtes utilisent les syntaxes suivantes:

INSERT INTO table (attribut1, attribut2, ... )
VALUES (valeur1, valeur2, ...)
UPDATE table
SET attribut2= valeur2
WHERE attribute1 = valeur
DELETE FROM table
WHERE attribute1 = valeur

Implémentation (Part IV)

Dans notre quatrième implémentation, nous allons considérer l'arborescence suivante:

server.py
data.db
/templates
base.html
index.html
form.html
create.html
update.html
delete.html

data.db

Depuis votre terminal, nous allons créer une base de données SQLite via la commande:

$ sqlite3 data.db

Nous allons ensuite créer une table contact contenant plusieurs champs.

sqlite> CREATE TABLE contact(
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT NOT NULL,
prenom TEXT NOT NULL,
mail TEXT NOT NULL,
tel TEXT NOT NULL);

Une fois que la table contact a été crée, nous pouvons y ajouter des éléments via la syntaxe INSERT INTO ... VALUES ....

sqlite> INSERT INTO CONTACT (nom,prenom,mail,tel)
VALUES
("Einstein","Albert","albert@emc2.com","06.00.00.00.00"),
("Shannon","Claude","claude@fesup2fmax.com","06.00.00.00.00"),
("Fourier","Joseph","joseph@maserie.fr","09.00.03.00.01");

Pour vérifier que tout s'est bien passé, il est possible de lister l'ensemble des éléments de la table contact via la commande

SELECT * FROM contact;

La commande .exit permet de quitter l'invite de commande sqlite3.

Templates HTML

Dans notre première implémentation, les urls permettant de modifier ou de supprimer les enregistrements étaient basées sur l'indexation de la liste contact_list. Nous allons maintenant utiliser le champ id de la table contact. Pour réaliser cette modification, nous devons remplacer les lignes 21 et 22 du template ìndex.html par

{% extends "base.html" %}

{% block titre %}Liste des contacts{% endblock %}

{% block contenu %}
<table>
    <tr>
        <th>Nom</th>
        <th>Prenom</th>
        <th>Telephone</th>
        <th>Email</th>
        <th>Actions</th>
    </tr>
    {% for contact in contact_list %}
    <tr>
        <td>{{contact.nom}}</td>
        <td>{{contact.prenom}}</td>
        <td>{{contact.tel}}</td>
        <td>{{contact.mail}}</td>
        <td>
            <a href="./update/{{contact.id}}">Modification</a>
            <a href="./delete/{{contact.id}}">Suppression</a>  
        </td>
    </tr>
    {% endfor %}
</table>

<a href="./create">Ajouter un contact</a>

{% endblock %}

Application Flask

Le code présenté ci-dessous présente le contenu de notre fichier server.py. Ce fichier comporte plusieurs fonctions permettant de simplifier la gestion de la base de données (get_db, query_db, change_db, close_connection). Ces fonctions sont appelées par nos fonctions permettant de lister, d'ajouter, de modifier ou de supprimer du contenu.

import sqlite3
from flask import Flask
from flask import render_template, request, redirect, url_for, g
app = Flask(__name__)

DATABASE = "data.db"

# Gestion de la base de données (copier-coller de la doc de FLASK)
def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
        db.row_factory = sqlite3.Row
    return db

def query_db(query, args=(), one=False):
    cur = get_db().execute(query, args)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

def change_db(query,args=()):
    cur = get_db().execute(query, args)
    get_db().commit()
    cur.close()

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

# Routage des URL et traitement

@app.route('/')
def index():
    contact_list=query_db("SELECT * FROM contact")
    return render_template("index.html",contact_list=contact_list)

@app.route('/create', methods=['GET', 'POST'])
def create():

    if request.method == "GET":
        return render_template("create.html",contact=None)

    if request.method == "POST":
        contact=request.form.to_dict()
        values=[contact["nom"],contact["prenom"],contact["mail"],contact["tel"]]
        change_db("INSERT INTO contact (nom,prenom,mail,tel) VALUES (?,?,?,?)",values)
        return redirect(url_for("index"))

@app.route('/update/<int:id>', methods=['GET', 'POST'])
def udpate(id):

    if request.method == "GET":
        contact=query_db("SELECT * FROM contact WHERE id=?",[id],one=True)
        return render_template("update.html",contact=contact)

    if request.method == "POST":
        contact=request.form.to_dict()
        values=[contact["nom"],contact["prenom"],contact["mail"],contact["tel"],id]
        change_db("UPDATE contact SET nom=?, prenom=?, mail=?, tel=? WHERE ID=?",values)
        return redirect(url_for("index"))

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

    if request.method == "GET":
        contact=query_db("SELECT * FROM contact WHERE id=?",[id],one=True)
        return render_template("delete.html",contact=contact)

    if request.method == "POST":
        change_db("DELETE FROM contact WHERE id = ?",[id])
        return redirect(url_for("index"))

Le code complet de notre application est disponible sur Github.