添加记录后,QTableView不会保留更改或更新

时间:2017-02-20 00:47:35

标签: sql user-interface pyqt qtgui qtsql

我正在构建一个GUI,它显示SQL数据库表的内容,并允许使用基本PyQ​​t4类QTableView和QSqlTableModel通过GUI添加和修改记录。我在编辑表格视图时遇到问题。

这是完整代码的最小,完整和可验证版本。它确实需要更改您正在使用的任何SQL数据库的登录信息,但除此之外,代码足以运行该接口:

import sys
import site
from subprocess import Popen
from PyQt4.QtCore import(Qt)
from PyQt4.QtGui import(QMainWindow, QApplication, QWidget, QPushButton, qApp,
QVBoxLayout, QTableView, QApplication)
from PyQt4.QtSql import(QSqlDatabase, QSqlQuery, QSqlQueryModel, QSqlTableModel)


class Window(QMainWindow):

    def __init__(self):

        super(Window, self).__init__()

        # Open and connect to database - this needs to be changed for the particular db you are using
        self.__database = QSqlDatabase.addDatabase('QPSQL')
        self.__database.setHostName('localhost')
        self.__database.setDatabaseName('~/Desktop/H2 testing/TESTING/db/db')
        self.__database.setPort(5435)
        self.__database.setUserName('grav')
        self.__database.setPassword('XXXXXXXXXX')
        self.__database.open()

        ok = self.__database.open()
        if ok == False:
            print 'Could not open database'
            print 'Text: ', self.__database.lastError().text()
            print 'Type: ', str(self.__database.lastError().type())
            print 'Number: ', str(self.__database.lastError().number())
            print 'Loaded drivers:', str(QSqlDatabase.drivers())

        # Create the QSqlTableModel using the database
        self.modelDirections = QSqlTableModel(None, self.__database)
        self.modelDirections.setTable('PUBLIC.DIRECTIONS')
        self.modelDirections.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.modelDirections.select()

        # Create the QTableView and connect to the QSqlTableModel
        self.tableDirections = QTableView()
        self.tableDirections.setModel(self.modelDirections)

        # Create a QPushButton to add a row to the table
        self.buttonAddDir = QPushButton('Add direction')
        self.buttonAddDir.clicked.connect(self.createDirection)

        # Set up the rest of the window with the QTableView and the QPushButton
        vbox = QVBoxLayout()
        vbox.addWidget(self.tableDirections)
        vbox.addWidget(self.buttonAddDir)
        stretchBox = QWidget()
        stretchBox.setLayout(vbox)
        self.setCentralWidget(stretchBox)
        self.show()


    def createDirection(self):

        # Define and execute query to determine current max direction serial
        model = QSqlQueryModel()
        query = 'SELECT * FROM directions WHERE id=(SELECT MAX(id) FROM directions)'
        model.setQuery(query)
        if model.record(0).value('id').toString() == '':
            newDirectionSerial = 0
        else:
            newDirectionSerial = int(model.record(0).value('id').toString()) + 1

        # Define queries to insert new direction record
        queryText = 'INSERT INTO public.directions (id, text, olddir, opposite) \
        VALUES (%s, NULL, 1, NULL)' % (newDirectionSerial)
        query = QSqlQuery()
        query.exec_(queryText)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    newWindow = Window()
    sys.exit(app.exec_())

在加载GUI时,表格在QTableView中正确显示。但是,我有两个问题:

  1. 我可以双击表格中的一个字段并开始编辑,但是当我双击另一个字段时,我在第一个字段中输入的任何内容都会消失。

    当我编辑字段然后切换到编辑新字段时,我收到消息"数据已更改"即使我输入的内容消失了。

    我最好的猜测是,数据在QSqlTableModel中被更改,但由于某种原因没有转换到底层数据库字段,并且当视图刷新时,它使用仍为空的数据库中的更新模型进行更新字段。

  2. 当我使用按钮添加新记录时,新记录不会显示。如果我关闭脚本然后再次启动它,则会显示新记录。

  3. 这些可能是两个不同的问题,但我感觉他们是相关的。

    自从首次发布此问题以来,我已设法收集有关问题1的更多信息:QSqlTableModel.dataChanged信号连接到记者功能后,我能够确认

    1. 当我编辑表格视图字段时,信号确实会触发,
    2. 由于查询存在问题,数据未从模型传输到数据库。数据库返回以下错误:
    3. ERROR: Column "text" not found; SQL statement: UPDATE PUBLIC.DIRECTIONS SET "text"='test' WHERE "id" = 1 AND "text" = 'constitutes' AND "dir" = 1 AND "opposite" = 2 [42122-164] (42S22) QPSQL: Unable to create query

      我能够通过另一个应用程序访问数据库,并且我测试了此查询的变体。剥离字段名称周围的引号并删除尾随[42122-164]会产生成功的查询以及我一直在寻找的行为。

      那很棒 - 但是我希望QSqlTableView能够处理这个问题,而且不知道如何处理。任何线索如何修改视图的查询行为(没有完全重建它)的线索将非常感激!

0 个答案:

没有答案