Accès à une base de données
Pour accéder à une base de données avec Python, il faut instancier un connecteur, puis établir une connexion, puis exécuter des requête à l’aide d’un curseur;
Voir Les bases de données avec Python

La connexion et le curseur doivent être fermés après utilisation afin de libérer la ressource.
Le protocole HTTP état sans état (chaque requête est indépendante), dans une application Web, la partie Python du programme est lancée plusieurs fois, à chaque requête HTTP de la part du client notamment.
Il faut donc s’assurer :
- qu’on n’ouvre pas plusieurs connexions à la base de données en même temps
- qu’on ferme bien la connexion lorsque le contexte d’exécution de Flask se ferme
Avec SQLite
Installation
Bibliothèque sqlite3 :
pip install pysqlite3
Utilisation
Les bases de données SQLite sont enregistrés dans des fichiers db enregistrés sur le serveur.
Les notions sont similaires aux autres SGBD :
- Création d’une connexion à la base :
db = sqlite3.connect('fichier.db') - Création d’un curseur :
cur = db.cursor() - Envoi d’une requête à l’aide du curseur :
cur.execute(requete, arguments) - Récupération de la réponse :
r = cur.fetchall()
ou bien confirmation des changements :db.commit() - Fermeture de la connexion :
db.close()
Connexion à la base
Le protocole HTTP est sans état, ce qui signifie qu’il ne mémorise aucune information entre deux requêtes.
Afin de conserver certaines informations entre deux requêtes, il faut les mettre en mémoire sur le navigateur du client, sous forme de cookies, chiffrés !
Afin de conserver une instance de la connexion à la base durant la durée d’une requête HTTP , on peut utiliser le contexte de l’application Flask :
import sqlite3
from flask import Flask, g
# g est une variable de contexte, pour stocker des données pendant un contexte d'application
app = Flask(__name__)
app.config['DATABASE'] = 'chemin_vers/ma_base.db'
def get_db():
if '_database' not in g: # la base de données n'est pas encore mémorisée dans le contexte
g._database = sqlite3.connect(current_app.config['DATABASE'])
g._database.row_factory = sqlite3.Row
return g._database
# Pour s'assurer que la connexion à la base est bien fermée
# à la fermeture du contexte (fin de la session)
@app.teardown_appcontext
def close_connection(exception):
db = g.pop('_database', None)
if db is not None:
db.close()
Accès aux données
Ainsi, dans chaque fonction de traitement des requêtes, on peut utiliser get_db() pour obtenir la connexion actuelle ouverte à la base de données.
Pour exécuter des requêtes SQL, on créé deux fonctions dédiées :
def read_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 write_db(query, args=()):
db = get_db()
cur = db.execute(query, args)
db.commit()
cur.close()
La fonction read_db renvoie une unique « ligne » (si one==True), ou bien une liste de « lignes », de type sqlite3.Row, un type d’objet pouvant se comporter comme une liste ET comme un dictionnaire :
Exemple : si r est une ligne sqlite3.Row comportant 3 champs 'nom', 'email' et 'mdp' :
>>> # Accès par le nom du champ >>> r['nom'] Blaise >>> # Accès par l'indice du champ >>> r[0] Blaise >>> # Itération sur tous les champs >>> for v in r: ... print(v) Blaise blaise.pascal@blaisepascal.fr 1234
Les requêtes doivent être passées sous forme d’une chaîne de caractères, les arguments placés dans un tuple. Leurs emplacements dans la chaîne de caractères sont repérés par le caractère ?.
Exemples :
read_db("SELECT * FROM users WHERE email=?", (email,), one = True)
write_db("INSERT INTO users VALUES (?,?,?)", (nom, email, hmdp))
Avec MySQL
Bibliothèque mysql-connector :
pip install mysql-connector-python
Les bases de données MySQL sont gérées par un serveur MySQL installé sur le serveur (pour Raspberry, voir Installer un serveur web Python).
Connexion à la base
Afin de conserver une instance de la connexion à la base durant la durée d’une requête HTTP, on peut utiliser le contexte de l’application Flask :
import mysql.connector
from flask import g
# g est une variable de contexte, pour stocker des données pendant un contexte d'application
DATABASE = 'ma_base'
def get_db():
db = getattr(g, '_database', None)
if db is None: # la base de données n'est pas encore mémorisée dans le contexte
db = g._database = mysql.connector.connect(host="localhost",
user="pi", password="raspberryNS1",
database=DATABASE)
return db
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
Accès aux données
Ainsi, dans chaque fonction de traitement des requêtes, on peut utiliser get_db() pour obtenir la connexion actuelle ouverte à la base de données.
Pour exécuter des requêtes SQL, on créé deux fonctions dédiées :
def read_db(query, args=(), one=False):
cur = get_db().cursor()
cur.execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
def write_db(query, args=()):
db = get_db()
cur = db.execute(query, args)
db.commit()
La fonction read_db renvoie une unique « ligne » (si one==True), ou bien une liste de « lignes », de type sqlite3.Row, un type d’objet pouvant se comporter comme une liste ET comme un dictionnaire :
Exemple : si r est une ligne sqlite3.Row comportant 3 champs 'nom', 'email' et 'mdp' :
>>> # Accès par le nom du champ >>> r['nom'] Blaise >>> # Accès par l'indice du champ >>> r[0] Blaise >>> # Itération sur tous les champs >>> for v in r: ... print(v) Blaise blaise.pascal@blaisepascal.fr 1234
Les requêtes doivent être passées sous forme d’une chaîne de caractères, les arguments placés dans un tuple. Leurs emplacements dans la chaîne de caractères sont repérés par la chaîne %s.
Exemples :
read_db("SELECT * FROM users WHERE email=%s", (email,), one = True)
write_db("INSERT INTO users VALUES (%s,%s,%s)", (nom, email, hmdp))
Utilisation de SQLalchémy
…
