基于 QSqlTableModel 就地编辑新记录的 QTableView 不会在 PyQt 中保存编辑

Posted

技术标签:

【中文标题】基于 QSqlTableModel 就地编辑新记录的 QTableView 不会在 PyQt 中保存编辑【英文标题】:QTableView based on QSqlTableModel editing new record in place doesn’t save edits in PyQt 【发布时间】:2020-06-25 10:50:19 【问题描述】:

我有一个 QTableView 的表单有一个添加新记录的按钮。记录出现,但我输入的任何数据都没有保存。事实上,一旦我添加了一条记录,就不会保存对 tableview 的任何编辑。只要不添加新记录,我就可以就地编辑。底层数据库是 Postgresql。

问题是,如何添加可以立即编辑的新记录?我在下面的代码中缺少什么?

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtWidgets import *
from phones import *

app=QApplication(sys.argv)

QTableView
QSqlTableModel

class Main(QMainWindow):

    def __init__(self, parent=None):

        QWidget.__init__(self, parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.cont_id = '9'
        self.populate_phones()
        self.ui.new_phone.clicked.connect(self.add_phone)

    def populate_phones(self):
        self.phone_model = QSqlTableModel(self)
        self.phone_model.setTable("contact_phones")
        self.phone_model.setFilter("contact_id='0'".format(self.cont_id))
        self.phone_model.select()

        self.phone_view = self.ui.phone_view
        self.phone_view.setModel(self.phone_model)  
        self.phone_view.resizeColumnsToContents()
        
    def add_phone(self):
        self.phone_model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        row = self.phone_model.rowCount()
        record = self.phone_model.record()
        record.setGenerated('id', False)            #primary key
        record.setValue('contact_id', self.cont_id) #foreign key
        self.phone_model.insertRecord(row, record)
        submit = self.phone_model.submitAll()
        #self.phone_model.select()
        phone_index_edit = QModelIndex(self.phone_model.index(row, self.phone_model.fieldIndex('phone_number'))) 
        self.ui.phone_view.edit(phone_index_edit)
        
if __name__=="__main__":

    db = QSqlDatabase.addDatabase("QPSQL");
    db.setHostName(server)
    db.setDatabaseName(database)
    db.setUserName(user)
    db.setPassword(pword)
    myapp = Main()
    myapp.show()
    sys.exit(app.exec_())

【问题讨论】:

【参考方案1】:

您正在将编辑策略设置为OnManualSubmit

在调用 submitAll() 或 revertAll() 之前,所有更改都将缓存在模型中。

一旦您通过调用edit() 开始编辑,将不会保存任何更改,而只会缓存。如果您关闭小部件之前没有调用submitAll(),这些更改将丢失;当您尝试添加新字段时也会发生这种情况,因为insertRecord 将仅提交插入记录的更改,而丢弃以前缓存的更改。

您可以保留默认的OnRowChange 编辑策略,或使用OnFieldChange

关于您的代码的进一步说明:

QApplication 实例的创建应该在 if __name__ 块内进行(开头的 QTableViewQSqlTableModel 行不应该在那里,因为它们什么都不做); 你调用的是QWidget的__init__,但是Main是QMainWindow的子类;您应该使用 QMainWindow.__init__(self) 或 QWidget 的子类; 由于您不会使用OnManualSubmit策略,因此无需在insertRecord之后提交; 没有必要创建一个新的 QModelIndex 实例,因为model.index() 已经返回了一个 QModelIndex;

【讨论】:

我已根据您的建议更新了我的代码。有些马虎是不好的剪切和粘贴,但你的建议真的很有帮助。我已经编辑了我的代码。 如果建议的答案不能完全解决您的问题,请使用 cmets 指定正在发生的事情以及预期的行为。 切勿根据答案修改您的问题:这会使问题和答案都变得混乱。

以上是关于基于 QSqlTableModel 就地编辑新记录的 QTableView 不会在 PyQt 中保存编辑的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 QSqlTableModel 在可编辑的 QTableView 中将值设置为 NULL

将行插入 QSqlTableModel

怎么在QSqlTableModel 中实现条件查找记录

子类化 QSqlTableModel 插入新值

就地编辑内容编辑

QT笔记:数据库总结之SQL模型类-QSqlTableModel模型