QSqlTableModel使用filter/sort查询并删除行row时,TableView给出的index.row()和数据库中table不一致,导致删除错误行
解决办法:查询和删除时使用相同model实例。或者不同的实例使用相同的filter。
Qt内部使用的是primaryKey对应的primaryValues(index.row())来删除,而primaryKey是在setTable的时候自动读取的。如果没有成功设置primaryKey,有可能会导致无法删除数据。
插入数据时,如果primaryKey在数据库是自动生成的,一般是integer,每次+1。从Qt插入record
数据(相当于sql里说的row)的时候,默认也会自动生成一个值,这时就会插入错误。
The issue is caused by a discrepancy between the SQLite-generated PK and the QT-generated PK.
- https://stackoverflow.com/questions/42319333/qsqlrecords-inserted-into-model-are-empty-blank-in-qtableview
解决办法,isGenerated要设置为False
record.setGenerated('tableid', False)
另外 Qt文档说了关于没有primary key的情况
QSqlRecord QSqlTableModel::primaryValues(int row) const
Returns a record containing the fields represented in the primary key set to the values at row. If no primary key is defined, the returned record will contain all fields.
This function was introduced in Qt 5.1.
- https://doc.qt.io/qt-5/qsqltablemodel.html
bool QSqlTableModel::selectRow(int row)
Refreshes row in the model with values from the database table row matching on primary key values. Without a primary key, all column values must match. If no matching row is found, the model will show an empty row.
Returns true if successful; otherwise returns false.
This function was introduced in Qt 5.0.
- https://doc.qt.io/qt-5/qsqltablemodel.html
Qt这个做法感觉不是很靠谱,不如读取数据库内部的RowNumber作为primaryKey,比如sqlite里的rowid。总之,QSql和其中的QSqlTableModel都不够灵活,不如自己写Model。
明显不是想让人直接访问的。QAbstractItemModel中是在QPersistentModelIndexData的实例d中,通过index访问。QStandardItemModel中是在model.invisibleRootItem()里。具体再细节的位置不想研究了,自己写model最方便。
由于QtConcurrent
是name space,所以PyQt,PySide都没有QtConcurrent.run()
,貌似以后也不会有。
曾经官方推荐用继承QThread重写 __init__
,__del__
和run
方法。后来有Qt内部核心大牛说这样用不对,推荐用QObject.moveToThread()方法。所以就用moveToThread吧。
model = MyModel()
thread = QtCore.QThread()
model.moveToThread(thread)
model.finished.connect(thread.quit)
thread.started.connect(model.func_to_run)
thread.finished.connect(func_to_run_after_thread_finished)
thread.start()
也可以写成一个函数把这段包起来,甚至写成一个装饰器。
不再更新,转投了PySide。