Bonjour,
le code ci dessous fonctionne mais j'ai quelques interrogations sur la manière d'aborder les choses...
je vient donc ici pour avoir quelques conseils sur les bonnes pratiques pour éviter de m'embarquer dans des impasses ou des tournures maladroites.
l'exemple ci dessous tourne avec sqlite mais l'application finale vise mysql (il est en cours d'install!).
l'idée est de permettre un affichage/modification d'une base de donnée via un affichage dans un QTableWidget

Principales interrogations:
1 - Sur chaque fonction, est-il nécessaire d'ouvrir/fermer une connexion et un curseur? Si non, je pense créer une seule connexion/curseur depuis le init du QMainWindow... Mais dans ce cas, comment s'assurer que le curseur et la connexion sont bien clôturés lors de la fermeture de l'application? (avec des thread parfois il y a des choses qui reste derrière... est-ce pareil avec le dialogue avec une base de donnée?)

2 - Dans l'exemple, chaque ajout de ligne implique la réécriture de toute la table... est-ce que cela ne créé pas des QTableWidgetItem "flottants" (issus de la table avant sa modification)? Vaut-il mieux cibler les ajouts vis à vis de la réelle nouvelle data? ou cela se pratique de tout réécrire?

3 - Le fait d'avoir la possibilité de capter une modification de la table (pour que l’utilisateur la mette à jour directement dans la base sql) et de permettre l'ajout dynamique d'une ligne induit un passage "obligé" dans la fonction appelée par le cellChanged.connect du QTableWidget à chaque cellule réécrite... obligation d'utiliser un blocksignal si besoin d'éviter cela?


merci pour vos conseils :-)


Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from PyQt5.QtWidgets import QApplication, QPushButton, QTableWidgetItem, QMainWindow, QVBoxLayout, QWidget, QTableWidget
import sqlite3
import random
import time
import sys
import os.path
 
 
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
 
        self.fichier_ddb = "pythonsqlite_000001.db"
 
        #vérifie l'existence de la bdd
        if os.path.isfile(self.fichier_ddb):
            data, self.nb_lignes, nb_colonnes, self.liste_columns_name = self.get_datas_from_ddb()
        else:
            #si inexistante, elle est créée puis remplie avec données fictives
            self.create_ddb()
            self.create_lines()
            #récupération de la data enregistrée dans la bdd
            data, self.nb_lignes, nb_colonnes, self.liste_columns_name = self.get_datas_from_ddb()
 
        #création de la fenetre qui affichera la représentation de la bdd sous forme de QTableWidget
        self.fenetre_globale = QWidget()
        self.layout_vertical = QVBoxLayout()
 
        self.table = QTableWidget()
        self.table.setColumnCount(nb_colonnes)
        self.table.setRowCount(self.nb_lignes)
        self.table.setHorizontalHeaderLabels(self.liste_columns_name)
        self.fill_table()
 
        self.bouton_ajouter = QPushButton("Ajouter ligne")
        #self.table.clicked.connect(self.table_clic)
 
        self.layout_vertical.addWidget(self.table)
        self.layout_vertical.addWidget(self.bouton_ajouter)
 
        self.bouton_ajouter.clicked.connect(self.insert_lines)
 
        self.fenetre_globale.setLayout(self.layout_vertical)
        self.setCentralWidget(self.fenetre_globale)
 
        self.resize(980, 400)
 
    def fill_table(self):
        # récupération de la data
        data, nb_lignes, nb_colonnes, self.liste_columns_name = self.get_datas_from_ddb()
 
        #insertion du nombre de lignes manquantes à la table
        for j in range(0, int(self.nb_lignes - nb_lignes), 1):
            self.table.insertRow(self.table.rowCount())
        self.nb_lignes = nb_lignes
        #redimensionnement de la table
        #si pas présente, l'ajout d'une ligne n'est plus dynamique
        self.table.setRowCount(nb_lignes)
        self.table.setHorizontalHeaderLabels(self.liste_columns_name)
 
        #remplissage de toute la table
        for index, ligne in enumerate(data):
            for index_colonne, colonne in enumerate(ligne):
                self.table.setItem(int(index), int(index_colonne), QTableWidgetItem(str(colonne)))
        self.table.cellChanged.connect(self.table_changed)
 
    def create_ddb(self):
 
        connection = sqlite3.connect(self.fichier_ddb)
        cursor = connection.cursor()
 
        sql_create_projects_table = """ CREATE TABLE IF NOT EXISTS projects (
                                            colonne0 TEXT,
                                            colonne1 TEXT,
                                            colonne2 TEXT,
                                            colonne3 TEXT,
                                            colonne4 TEXT,
                                            colonne5 TEXT,
                                            colonne6 TEXT,
                                            colonne7 TEXT,
                                            colonne8 TEXT)"""
        if connection is not None:
            cursor.execute(sql_create_projects_table)
            connection.commit()
        else:
            print("Error! cannot create the database connection.")
        cursor.close()
        connection.close()
 
    def create_lines(self):
        #ne sert qu'à simuler une bdd pré-existante
        connection = sqlite3.connect(self.fichier_ddb)
        cursor = connection.cursor()
        sql = """INSERT INTO projects (colonne0, colonne1, colonne2, colonne3, colonne4, colonne5, colonne6, colonne7, colonne8) VALUES(?,?,?,?,?,?,?,?,?)"""
        for i in range(0, 10, 1):
            cursor.execute(sql, (str(i),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10)))
        cursor.close()
        connection.commit()
        connection.close()
 
 
    def insert_lines(self):
        #sert à simuler la création d'une ligne dans la bdd (pas forcément sur le même PC)
        connection = sqlite3.connect(self.fichier_ddb)
        cursor = connection.cursor()
        sql = """INSERT INTO projects (colonne0, colonne1, colonne2, colonne3, colonne4, colonne5, colonne6, colonne7, colonne8) VALUES(?,?,?,?,?,?,?,?,?)"""
        for i in range(0, 1, 1):
            cursor.execute(sql, (str(i + self.nb_lignes),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10),str(random.random()*10),
                                 str(random.random()*10)))
        cursor.close()
        connection.commit()
        connection.close()
        self.fill_table()
 
    def get_datas_from_ddb(self):
        debut = time.time()
        connection = sqlite3.connect(self.fichier_ddb)
        cursor = connection.cursor()
        cursor.execute("SELECT * FROM projects")
        rows = cursor.fetchall()
        names = list(map(lambda x: x[0], cursor.description))
        colonnes = len(rows[0])
        lignes = len(rows)
        connection.close()
        print("Get All Data: " + str(time.time()-debut))
        return rows, lignes, colonnes, names    
 
 
    def table_changed(self):
        try:
            debut = time.time()
            connection = sqlite3.connect(self.fichier_ddb)
            cursor = connection.cursor()
            dt_updated, new_val, colonne_updated = (self.table.item(self.table.currentRow(), 0).text(),
                                                        self.table.item(self.table.currentRow(), self.table.currentColumn()).text(),
                                                        self.liste_columns_name[int(self.table.currentColumn())])
            new_val = self.table.item(self.table.currentRow(), self.table.currentColumn()).text()
            sql_update= """UPDATE projects SET """ + str(colonne_updated) + """ = ? WHERE colonne0 = ?"""
            data_new = (new_val, dt_updated)
            cursor.execute(sql_update, data_new)
            cursor.close()
            connection.commit()
            connection.close()
            print(str(time.time()-debut))
 
        except Exception as er:
            print(er)
 
if __name__ == "__main__":
    appli = QApplication(sys.argv)
    fenetre_main = MainWindow()
    fenetre_main.show()
    sys.exit(appli.exec_())