QSqlQueryModel 在添加和更新记录后刷新数据的不同行为
Different behavior of QSqlQueryModel for refresing data after adding and update record
我得到了带有用于添加和编辑记录的菜单的 QTableView。该模型是使用 QSqlQueryModel 准备的,因为它还显示了记录的关联数据(金额总和)。
完成我想刷新的操作后 table。
我不明白为什么对于编辑操作执行 model.query().exec_()
来查看更新就足够了,但是对于新操作,我还需要执行 model.setQuery(model.query())
来查看新插入的行。
def build_model(self):
self.model = QSqlQueryModel()
self.model.setQuery("SELECT b.id, b.name, SUM(coalesce(s.amount, 0.00)) as amount\
FROM budget AS b\
LEFT OUTER JOIN transaction_split as s ON s.id_budget = b.id\
GROUP BY b.id\
ORDER BY name")
self.table.setModel(self.model)
def act_new(self):
dlg = BudgetEd()
dlg.dialog.exec()
self.model.query().exec_()
self.model.setQuery(self.model.query()) # Why I need to this? to refresh the view
def act_ed(self):
# ... retrieve id_
dlg = BudgetEd(id_)
dlg.dialog.exec()
self.model.query().exec_() # or why this works without setting the query in the model again?
最后,我决定不使用 QSqlQueryModel(),因为它与 Windows 上的 sqlalchemy 查询冲突(windows 锁定文件以供读取)。
我实现了自己的 TableModel(QAbstractTableModel),因为这是一项非常简单的任务:
class TableModel(QAbstractTableModel):
sql: text
def __init__(self):
super().__init__()
self._data = []
self.sql = None
def set_sql(self, sql: str):
self.sql = text(sql)
def load_data(self):
sess: session = Session()
self._data = sess.execute(self.sql).fetchall()
self.layoutChanged.emit()
def set_data(self, data):
self._data = data
def data(self, index: PySide2.QtCore.QModelIndex, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole:
value = self._data[index.row()][index.column()]
return value
if role == Qt.UserRole:
return self._data[index.row()][index.column()]
if role == Qt.TextAlignmentRole:
value = self._data[index.row()][index.column()]
if isinstance(value, int) or isinstance(value, float):
return int(Qt.AlignRight | Qt.AlignVCenter)
def rowCount(self, parent: PySide2.QtCore.QModelIndex = ...) -> int:
return len(self._data)
def columnCount(self, parent: PySide2.QtCore.QModelIndex = ...) -> int:
return len(self._data[0])
# ...
def act_new(self):
dlg = AssetEd()
dlg.dialog.exec()
self.model.load_data()
我得到了带有用于添加和编辑记录的菜单的 QTableView。该模型是使用 QSqlQueryModel 准备的,因为它还显示了记录的关联数据(金额总和)。
完成我想刷新的操作后 table。
我不明白为什么对于编辑操作执行 model.query().exec_()
来查看更新就足够了,但是对于新操作,我还需要执行 model.setQuery(model.query())
来查看新插入的行。
def build_model(self):
self.model = QSqlQueryModel()
self.model.setQuery("SELECT b.id, b.name, SUM(coalesce(s.amount, 0.00)) as amount\
FROM budget AS b\
LEFT OUTER JOIN transaction_split as s ON s.id_budget = b.id\
GROUP BY b.id\
ORDER BY name")
self.table.setModel(self.model)
def act_new(self):
dlg = BudgetEd()
dlg.dialog.exec()
self.model.query().exec_()
self.model.setQuery(self.model.query()) # Why I need to this? to refresh the view
def act_ed(self):
# ... retrieve id_
dlg = BudgetEd(id_)
dlg.dialog.exec()
self.model.query().exec_() # or why this works without setting the query in the model again?
最后,我决定不使用 QSqlQueryModel(),因为它与 Windows 上的 sqlalchemy 查询冲突(windows 锁定文件以供读取)。 我实现了自己的 TableModel(QAbstractTableModel),因为这是一项非常简单的任务:
class TableModel(QAbstractTableModel):
sql: text
def __init__(self):
super().__init__()
self._data = []
self.sql = None
def set_sql(self, sql: str):
self.sql = text(sql)
def load_data(self):
sess: session = Session()
self._data = sess.execute(self.sql).fetchall()
self.layoutChanged.emit()
def set_data(self, data):
self._data = data
def data(self, index: PySide2.QtCore.QModelIndex, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole:
value = self._data[index.row()][index.column()]
return value
if role == Qt.UserRole:
return self._data[index.row()][index.column()]
if role == Qt.TextAlignmentRole:
value = self._data[index.row()][index.column()]
if isinstance(value, int) or isinstance(value, float):
return int(Qt.AlignRight | Qt.AlignVCenter)
def rowCount(self, parent: PySide2.QtCore.QModelIndex = ...) -> int:
return len(self._data)
def columnCount(self, parent: PySide2.QtCore.QModelIndex = ...) -> int:
return len(self._data[0])
# ...
def act_new(self):
dlg = AssetEd()
dlg.dialog.exec()
self.model.load_data()