Почему пропадают строки? QTableView + QSqlRelationalTableModel

Рейтинг: 0Ответов: 1Опубликовано: 15.03.2023

Не могу разобраться со странным поведением отображения QSqlRelationalTableModel.
setEditStrategy модели установлен в OnFieldChange. Пытаюсь изменить значения в ячейках, но вся строка исчезает и нельзя изменить другие ячейки этой строки. Почему так?

введите сюда описание изображения введите сюда описание изображения

Код:

from ui_ui import Ui_Form
from PyQt5 import QtWidgets
from PyQt5.QtSql import QSqlRelationalTableModel, QSqlDatabase, QSqlTableModel, 
QSqlRelationalDelegate, QSqlRelation
import sys
import sqlite3

# create db for example, run once
# with sqlite3.connect('db.db') as con:
#     cur = con.cursor()
#     cur.execute('CREATE TABLE IF NOT EXISTS tab ("static_col", "relation_col1", "relation_col2")')
#     cur.execute('CREATE TABLE IF NOT EXISTS relation ("rel")')
#     cur.execute('INSERT INTO tab(static_col) VALUES ("Lorem"), ("ipsum"), ("dolor"),("sit")')
#     cur.execute('INSERT INTO relation(rel) VALUES (69), (322)')

db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('db.db')
db.open()

class MainWindow(QtWidgets.QWidget, Ui_Form):

    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.setupUi(self)

        table_model = QSqlRelationalTableModel(db=db)
        table_model.setTable('tab')
        table_model.select()
        table_model.setEditStrategy(0)
        self.tableView_1.setModel(table_model)

        delegate = QSqlRelationalDelegate(self.tableView_1)
        table_model.setRelation(1, QSqlRelation('relation', 'rel', 'rel'))
        self.tableView_1.setItemDelegateForColumn(1, delegate)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())

Код ui_ui:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(684, 300)
        self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.tableView_1 = QtWidgets.QTableView(Form)
        self.tableView_1.setObjectName("tableView_1")
        self.horizontalLayout.addWidget(self.tableView_1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))

Ответы

▲ 0Принят

я потратил неделю на поиск ответа, поэтому напишу решение сюда, чтобы кто-то если столкнется с такой же трудностью не тратил время как я.

Проблема заключается в неявном определении primary и foreign ключей. В БД должны быть четко и явно установлены связи и типы столбцов, иначе работать не будет.

UPDATE: после тестов, как оказалось, даже при соблюдении всех условий QSqlRelation всё равно ломает представление, проблема не диагностируется, трудно исправима и причины непонятны, вот тут описана подробно.
В итоге я отказался от использования QSqlRelation и назначил делегаты через список строк из этого примера, чего и всем советую