pythonsqlitepyqt5qcomboboxqsqlrelationaltablemodel

map data in combobox with relation with more than 256 items


I have a QSqlRelationalTableModel with a related table with more than 256 rows. The relation is working perfect, i have in column 1 the related values from the "relation_table"

But mapping the data in the combobox and submiting to the db by selecting in the combobox, works only for the first 256 rows.

Adding a value higher than 256 to the db by hand, the related value do not map to the combobox, but in the tableview is the relation correct.

Otherwise displays a click on the combobox all items in the list of the combobox.

I have the data from a SQLITE-database which has a this structure:

CREATE TABLE `base_table` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `rel_id` INTEGER);
INSERT INTO `base_table` VALUES (1, 1);
CREATE TABLE "rel_table" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `name` TEXT);
INSERT INTO `rel_table` VALUES (1,'aaa');

Here is a simple working example:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDataWidgetMapper, QVBoxLayout,\
    QWidget, QComboBox, QApplication, QTableView, QPushButton
from PyQt5.QtSql import QSqlRelationalTableModel, QSqlRelation,\
    QSqlRelationalDelegate, QSqlDatabase


def submitModel():
    mapper.submit()
    model.submitAll()

app = QApplication(sys.argv)
window = QWidget()

combobox = QComboBox()
tableview = QTableView()
button = QPushButton('submit')
layout = QVBoxLayout()

layout.addWidget(combobox)
layout.addWidget(tableview)
layout.addWidget(button)

con = QSqlDatabase.addDatabase('QSQLITE')
con.setDatabaseName('test_db.sqlite')
con.open()

model = QSqlRelationalTableModel()
model.setTable("base_table")
model.setRelation(1, QSqlRelation("rel_table", "id", "name"))
model.select()

relation_model = model.relationModel(1)
relation_model.setSort(0, Qt.AscendingOrder)

while relation_model.canFetchMore():
    relation_model.fetchMore()

relation_model.select()

combobox.setModel(relation_model)
combobox.setModelColumn(1)

mapper = QDataWidgetMapper()
mapper.setModel(model)
mapper.setItemDelegate(QSqlRelationalDelegate())
mapper.addMapping(combobox, 1)
mapper.toFirst()

tableview.setModel(model)
tableview.setItemDelegate(QSqlRelationalDelegate(tableview))

button.clicked.connect(submitModel)

window.setLayout(layout)
window.setGeometry(300, 300, 250, 300)
window.show()
sys.exit(app.exec_())

To test the issue in the example above, you have to fill the table "rel_table" with more than 256 rows!

How can i get a correct working combobox, that displays a relation for all related items?


Solution

  • Remove relation_model.select().


    TL; DR;

    In the private Qt API, the populateDictionary() function is called which only loads a maximum of 256 (magic number that seems to be the number of rows obtained in each transaction) rows since it does not use canFetchMore() and fetchMore(). So it seems that the OP knows that limitation because it uses canFetchMore() and fetchMore() to load the new data but the error is to call again relation_model.select() that loads at most the first 256 elements eliminating the effect of canFetchMore() and fetchMore().