Search code examples
pythonmysqlpyqtpyqt5qsqltablemodel

PyQt5 QSqlTableModel not updating changes to database


I have a PyQt5 Application connecting to a MySQL database. I made two views connected to the same model. The views pull in data from the database just fine. Any change I make to any field in one is reflected in the other. But it does not update the database. I tried leaving it idle for 15 minutes and it didn't update the database.

This is my code:

from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
from PyQt5.QtWidgets import QTableView, QApplication
import sys

app = QApplication(sys.argv)

db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("usrdb")
db.setUserName("usr")
db.setPassword("passwrd")
db.open()

testModel = QSqlTableModel()
qry = QSqlQuery("select * from test", db)
testModel.setQuery(qry)
testModel.setEditStrategy(QSqlTableModel.OnFieldChange)

testView = QTableView()
testtView.setModel(testModel)
testView2 = QTableView()
testView2.setModel(testModel)

testView.show()
testView2.show()

app.exec_()

The second problem I'm having is, once I change the data in one cell, the view doesn't let me edit the data in any other cell. They are selectable, but not editable.


Solution

  • Fixed both my problems. pyqt documentation advices not to use setQuery.

    You should normally not call it(setQuery) on a QSqlTableModel. Instead, use setTable(), setSort(), setFilter(), etc., to set up the query.

    Updated code:

    from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
    from PyQt5.QtWidgets import QTableView, QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    db = QSqlDatabase.addDatabase("QMYSQL")
    db.setHostName("localhost")
    db.setDatabaseName("usrdb")
    db.setUserName("usr")
    db.setPassword("passwrd")
    db.open()
    
    testModel = QSqlTableModel()
    testModel.setTable("test")
    testModel.setEditStrategy(QSqlTableModel.OnFieldChange)
    testModel.select()
    
    testView = QTableView()
    testtView.setModel(testModel)
    
    app.exec_()
    

    This updates the database as soon as the edits are made, and also lets me do multiple edits on a view.