这是对这个问题的跟进。在那里,我们创建了 QSqlQueryModel 的可编辑子类,用于复杂查询。现在我需要添加 QTableModel 的 setEditStrategy 之类的功能,这样我就可以缓存所有更改并使用按钮接受或恢复它们。PyQt 显然不允许多重继承,我找不到足够的文档来在我的自定义模型中重新实现此方法,因此这里有一个问题:
如何在可编辑的 QSqlQueryModel 中重新实现 QSqlTableModel.setEditStragety(或类似的东西),包括 RevertAll() 和 SubmitAll()?
这是一个 CVME:(我已经对我想开始工作的示例类的部分进行了注释)
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel, QSqlTableModel
from PyQt5.QtWidgets import QApplication, QTableView, QWidget, QGridLayout
from PyQt5.Qt import QPushButton
db_file = "test.db"
def create_connection(file_path):
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(file_path)
if not db.open():
print("Cannot establish a database connection to {}!".format(file_path))
return False
return True
def fill_tables():
q = QSqlQuery()
q.exec_("DROP TABLE IF EXISTS Manufacturers;")
q.exec_("CREATE TABLE Manufacturers (Company TEXT, Country TEXT);")
q.exec_("INSERT INTO Manufacturers VALUES ('VW', 'Germany');")
q.exec_("INSERT INTO Manufacturers VALUES ('Honda' , 'Japan');")
q.exec_("DROP TABLE IF EXISTS Cars;")
q.exec_("CREATE TABLE Cars (Company TEXT, Model TEXT, Year INT);")
q.exec_("INSERT INTO Cars VALUES ('Honda', 'Civic', 2009);")
q.exec_("INSERT INTO Cars VALUES ('VW', 'Golf', 2013);")
q.exec_("INSERT INTO Cars VALUES ('VW', 'Polo', 1999);")
class SqlQueryModel_editable(QSqlQueryModel):
"""a subclass of QSqlQueryModel where individual columns can be defined as editable
"""
def __init__(self, editables):
"""editables should be a dict of format:
{INT editable_column_nr : (STR update query to be performed when changes are made on this column
INT model's column number for the filter-column (used in the where-clause),
)}
"""
super().__init__()
self.editables = editables
def flags(self, index):
fl = QSqlQueryModel.flags(self, index)
if index.column() in self.editables:
fl |= Qt.ItemIsEditable
return fl
def setData(self, index, value, role=Qt.EditRole):
if role == Qt.EditRole:
mycolumn = index.column()
if mycolumn in self.editables:
(query, filter_col) = self.editables[mycolumn]
filter_value = self.index(index.row(), filter_col).data()
q = QSqlQuery(query.format(value, filter_value))
result = q.exec_()
if result:
self.query().exec_()
else:
print(self.query().lastError().text())
return result
return QSqlQueryModel.setData(self, index, value, role)
def setFilter(self, myfilter):
text = (self.query().lastQuery() + " WHERE " + myfilter)
self.setQuery(text)
class Example(QWidget):
def __init__(self):
super().__init__()
self.resize(400, 150)
self.createModel()
self.initUI()
def createModel(self):
editables = {1 : ("UPDATE Manufacturers SET Country = '{}' WHERE Company = '{}'", 2)}
self.model = SqlQueryModel_editable(editables)
query = '''
SELECT (comp.company || " " || cars.model) as Car,
comp.Country,
cars.company,
(CASE WHEN cars.Year > 2000 THEN 'yes' ELSE 'no' END) as this_century
from manufacturers comp left join cars
on comp.company = cars.company
'''
q = QSqlQuery(query)
self.model.setQuery(q)
self.model.setFilter("cars.Company = 'VW'")
# self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
def initUI(self):
self.layout = QGridLayout()
self.setLayout(self.layout)
self.view = QTableView()
self.view.setModel(self.model)
self.view.hideColumn(2)
self.layout.addWidget(self.view,0,0,1,2)
self.accept_btn = QPushButton("Accept Changes")
# self.accept_btn.clicked.connect(self.model.submitAll)
self.layout.addWidget(self.accept_btn, 1,0)
self.reject_btn = QPushButton("Reject Changes")
# self.reject_btn.clicked.connect(self.model.revertAll)
self.layout.addWidget(self.reject_btn, 1,1)
if __name__ == '__main__':
app = QApplication(sys.argv)
if not create_connection(db_file):
sys.exit(-1)
fill_tables()
ex = Example()
ex.show()
sys.exit(app.exec_())
编辑以澄清:
我需要一个可编辑的 QSqlQueryModel,我可以在其上使用submitAll()
and revertAll()
,以便模型数据的更改仅在单击接受按钮后才被接受,或者可以使用“拒绝”按钮恢复。