2 Attachment(s)
QSqlRelationalDelegate displays foreign_key - id instead of name/value from Combobox
I am trying to add new rows to QSqlRelationalModel which is represented in QTableView. This new row is populated by the user, and on fieldChange should be submitted to DB.
I have set proper QSqlRelationalDelegate and proper QSqlRelations in the model:
Code:
table_name = 'book_of_accounts'
self.table_name = table_name
self.table_model.setTable(table_name)
self.
table_model.
setRelation(4,
QSqlRelation('account_type',
'id',
'name'))self.
table_model.
setRelation(7,
QSqlRelation('subconto1',
'id',
'name'))self.
table_model.
setRelation(8,
QSqlRelation('subconto2',
'id',
'name'))self.
table_model.
setRelation(9,
QSqlRelation('subconto3',
'id',
'name'))
self.
table_model.
setEditStrategy(QSqlTableModel.
EditStrategy.
OnFieldChange)self.table_model.select()
self.
tableView = QtWidgets.
QTableView(self.
verticalLayoutWidget)self.tableView.setModel(self.table_model)
Displaying and updating existing data from the database works fine. Columns with related data change to Comboboxes and I can choose options from the related tables.
However, when I try to create a new record by adding a row to the model, Comboboxes allow me to choose the proper value from the dropdown list, but after choosing it, the value changes to the ID of the related record as if no relational delegate was set:
Code:
def addRow(self):
self.table_model.insertRows(count, 1)
self.tableView.scrollToBottom()
self.tableView.selectRow(count)
Here is how I can choose a correctly displayed option:
Attachment 13699
But once I close the editor, the text is replaced with a foreign key:
Attachment 13698
Once I fill out all fields and select another row, the data is submitted and the row is displayed correctly again. So this only happens while adding a new row.
I am using a QFilterSortProxyModel too, but it has no effect on the described behavior. This bug is persistent in both pyqt5 and pyqt6.
While debugging I discovered that in QSqlRelationalDelegate`s setModelData, model.data() contains the corresponding foreign keys when the method is executed.
I have a SO question, which describes the problem with a bit more code as context.
Am I missing something obvious here? How can tackle this issue?
Re: QSqlRelationalDelegate displays foreign_key - id instead of name/value from Combo
short answer: QFilterSortProxyModel cant work using a proxy model.
long answer: need to subclass QSqlRelationalDelegate to search in the proxy mode, the source model. and call the base function using the model and index if the sourceModel()
1- need to find the first not-proxy model using the 'index', and the mapped model index related to proxy index 'index' and return the source model index and the index mapped from the proxy model
Code:
std
::tuple<QAbstractItemModel
*, QModelIndex> findSourceModel
(QModelIndex index
) const{
while( source_model->inherits("QAbstractProxyModel") ){
//qDebug() << "class name from proxy model " << source_model->metaObject()->className();
source_index = static_cast<QAbstractProxyModel *>(source_model)->mapToSource(source_index);
source_model = static_cast<QAbstractProxyModel *>(source_model)->sourceModel();
}
return {source_model, source_index};
}
and use the returned values whit the base class implementation of QSqlRelationalDelegate
Code:
{
auto[source_model, source_index] = findSourceModel(index);
}
NOTE:
for a not proxy model. i refer to any subclass of QAbstractProxyModel, mainly a QSortProxyModelor QIdentityProxyModelsubclass
I apologize for responding with a code in C++, but I haven't programmed in Python for a long time, it should be easy to convert it to Python.
I hope it is useful to you