我正在构建一个GUI,它显示SQL数据库表的内容,并允许使用基本PyQt4类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中正确显示。但是,我有两个问题:
我可以双击表格中的一个字段并开始编辑,但是当我双击另一个字段时,我在第一个字段中输入的任何内容都会消失。
当我编辑字段然后切换到编辑新字段时,我收到消息"数据已更改"即使我输入的内容消失了。
我最好的猜测是,数据在QSqlTableModel中被更改,但由于某种原因没有转换到底层数据库字段,并且当视图刷新时,它使用仍为空的数据库中的更新模型进行更新字段。
当我使用按钮添加新记录时,新记录不会显示。如果我关闭脚本然后再次启动它,则会显示新记录。
这些可能是两个不同的问题,但我感觉他们是相关的。
自从首次发布此问题以来,我已设法收集有关问题1的更多信息:
将QSqlTableModel.dataChanged
信号连接到记者功能后,我能够确认
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能够处理这个问题,而且不知道如何处理。任何线索如何修改视图的查询行为(没有完全重建它)的线索将非常感激!