Gestion et usage des bases de données en PyQt
Introduction
1. Les bases de données relationnelles
Le développement d’application « desktop », comme nous le faisons en développement PyQt, implique fréquemment l’usage de bases de données, et ce pour répondre en premier lieu au besoin de faire persister des données au-delà même de leur manipulation au cours d’une session. Une application PyQt est donc en mesure d’accéder à une base de données pour la requêter, c’est-à-dire pour interroger son contenu mais également pour modifier celui-ci (ajouter des données, les modifier, les supprimer).
Il existe différentes familles de bases de données. La plus importante et la plus utilisée est celle des bases de données relationnelles.
On entend par « base de données relationnelle » une base dans laquelle les données sont stockées dans des tables. Chaque ligne de la table est nommée un tuple. Les tables sont reliées entre elles par des relations de cardinalité obtenues par l’utilisation des clés primaires et étrangères.
Une base de données relationnelle est créée, gérée, administrée par un système de gestion de base de données relationnelle (SGBDR). Les plus célèbres sont MySQL...
Exemple détaillé avec SQLite
1. Création de la base de données
Pour créer la base de données, nous aurons besoin du sous-module de PyQt dédié aux bases de données relationnelles, que l’on importe en début de code.
from PyQt5 import QtSql
Nous allons créer une base de données incluant des titres de livres d’informatique. Nous stockerons également dans la base de données le sujet du livre (C#, Python, Java, etc.), ainsi que l’identité de l’auteur ou de l’autrice.
Il y aura donc trois tables dans la base de données : une table des titres d’ouvrages, une table des auteurs et une table des sujets techniques. On considère ici qu’un ouvrage n’a qu’un seul auteur et qu’un seul sujet technique.
Un sujet technique (Python par exemple) sera lié potentiellement à plusieurs ouvrages. Ce sera également le cas d’un auteur, qui pourra être lié, lui aussi, à plusieurs ouvrages Il existe ainsi une relation « un à plusieurs » entre respectivement les tables SUJET et PERSONNE d’une part et la table LIVRE d’autre part.
Bien sûr, cette modélisation est imparfaite et n’épouse pas toutes les situations : elle nous permet toutefois d’ébaucher un stockage structuré d’informations sur le sujet.
Représentons ce que l’on appelle le modèle de données à l’aide d’un diagramme de classes UML simplifié permettant de représenter les cardinalités des deux relations. Dans ce diagramme, le « plusieurs » de « relation un à plusieurs » est représenté par le symbole « * ».
Diagramme de classes simplifié
Ce diagramme de classes nous permet d’établir le schéma physique de données (SPD), c’est-à-dire le « plan » de la base de données.
Le schéma physique de données (SPD) de la base de données d’exemple
Si on détaille ce schéma physique de données :
-
La table LIVRE de clé primaire id possède les champs suivants : le titre du livre, son année de sortie, et deux clés...
Plus loin avec l’utilisation de QSqlTableModel
1. Introduction
La section précédente montre la grande puissance de l’usage des bases de données relationnelles en PyQt, et par ailleurs de l’usage de SQL avec cette technologie. Il existe cependant d’autres classes qui permettent d’aller encore plus loin dans l’intégration de SQL en PyQt. En effet, la classe QSqlTableModel permet en quelques lignes de créer un contrôle graphique directement lié au contenu d’une table de la base de données.
Ainsi, le développement s’en trouve grandement facilité : nul besoin de développer à la fois la partie base de données et l’exploitation graphique des données dans des widgets. On fait en quelque sorte les deux en même temps.
2. Exemple d’utilisation
Rappelons-nous des considérations sur le paradigme MVC. Schématiquement, nous allons ici associer une vue (une fenêtre graphique) avec un modèle, en l’occurrence une table de la base de données précédemment créée.
On commence, comme à l’habitude, par déclarer les imports dont nous aurons besoin.
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout,
QPushButton, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QTableView, QDialog
from PyQt5...
L’utilisation de QSqlRelationalTableModel
1. Introduction
Le précédent exemple basé sur l’usage de QSqlTableModel avait l’avantage et la simplicité de manipuler une table qui n’utilisait pas de clé étrangère. En effet, l’utilisation d’une relation via une clé étrangère poserait alors le problème d’obtenir à l’affichage uniquement la valeur de la clé étrangère et non les éléments compréhensibles issus de la table liée par cette relation.
La classe QSqlRelationalTableModel permet de résoudre ce problème, c’est-à-dire que l’on peut, grâce à elle, remonter les informations depuis les tables liées pour les afficher, puis les sélectionner.
La documentation en ligne relative à cette classe est disponible ici : https://doc.qt.io/qt-5/qsqlrelationaltablemodel.html
2. Exemple d’utilisation
Comme à habituellement, on commence par déclarer les différents imports nécessaires.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout,
QPushButton, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QTableView, QDialog
from PyQt5 import QtSql, QtGui, QtCore
from PyQt5.QtSql import QSqlTableModel, QSqlDatabase, QSqlQuery
from PyQt5.QtSql import QSqlRelationalTableModel...
Le mapping de données avec QDataWidgetMapper
1. Introduction
Les deux exemples précédents mettent en perspective la possibilité de faire communiquer vue et modèle et d’afficher ainsi l’ensemble d’une table dans un composant similaire à un tableau.
Il arrive fréquemment que l’on ne souhaite pas un tel rendu et que l’on désire au contraire une présentation sous forme de fiche, c’est-à-dire une vue détaillée qui correspond à une et une seule ligne d’une table ou d’un modèle. Typiquement, dans cette hypothèse, une classe comme QSqlRelationalTableModel n’est pas adaptée au besoin. Nous utiliserons ici la classe QDataWidgetMapper.
La documentation de cette classe est accessible à cette adresse : https://doc.qt.io/qt-5/qdatawidgetmapper.html
2. Exemple d’utilisation
L’idée est donc ici de faire une fenêtre permettant de naviguer parmi les lignes de la table SUJET, et ce dans les deux sens de progression dans la base de données (« avant » et « arrière »). On affiche une ligne à la fois.
On commence par ajouter les imports nécessaires.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit,
QPushButton
from PyQt5.QtWidgets import QTableView, QDialog, QFormLayout...