I am newbie with Pyqt and need help with setting setData on QAbstractTableModel with QSqlRelationalTableModel table model
I have this simple code and I dont now how to implement setData function. I can't set value to field. I'm getting TypeError: 'QSqlRelationalTableModel' object is not subscriptable error.
Also, how to perform calculatation on column (eg. Total column)?
from pyexpat import model
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QGridLayout, QHeaderView, QMessageBox,
QTableView, QMainWindow, QWidget)
from PyQt5.QtSql import QSqlDatabase, QSqlRelationalTableModel, QSqlTableModel
from PyQt5.QtSql import QSqlRelation, QSqlRelationalDelegate
from PyQt5 import QtCore
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, QRect, Qt
from datetime import date
from time import strftime
from numpy import record
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, model):
super().__init__()
self._model = model
# Create the data method
def data(self, index, role):
value = self._model.record(index.row()).value(index.column())
if role == Qt.ItemDataRole.DisplayRole:
if isinstance(value, int) and index.column() == 0:
return f'# {value}'
if isinstance(value, int) and index.column() == 1:
# Format the currency value
return "${: ,.2f}".format(value)
if role == Qt.EditRole:
return self._model[index.row()][index.column()]
return value
if role == Qt.ItemDataRole.DecorationRole:
if isinstance(value, int) and index.column() == 0:
return QtGui.QIcon('data/icons/hashtag_icon.png')
if isinstance(value, str) and index.column() == 9:
return QtGui.QIcon('data/icons/calendar.png')
# Create the headerData method
def headerData(self, section: int, orientation: Qt.Orientation, role: int):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return self._model.headerData(section, orientation, role=role)
# Create the rowCount method
def rowCount(self, parent: QModelIndex) -> int:
return self._model.rowCount()
# Create the columnCount method
def columnCount(self, parent: QModelIndex) -> int:
return self._model.columnCount()
def setData(self, index, value, role):
if not index.isValid():
return False
if role == Qt.EditRole:
self._model[index.row()][index.column()]=value
self.dataChanged.emit(index, index,)
return True
return False
def flags(self, index):
return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable
# Inherit from QMainWindow
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
# Set the window title
self.setWindowTitle('QTable Example')
self.window_width, self.window_height = 1000, 700
self.setMinimumSize(self.window_width, self.window_height)
# Create the model
model = QSqlRelationalTableModel(self)
# Set the table to display
model.setTable('obracundetails')
model.setEditStrategy(QSqlRelationalTableModel.EditStrategy.OnFieldChange)
# Set relations for related columns to be displayed
#model.setRelation(1, QSqlRelation('products', 'ProductID', 'Price'))
model.setRelation(8, QSqlRelation('asortiman', 'asortiman_id', 'naziv'))
model.setRelation(9, QSqlRelation('obracunmain', 'obracunmain_id', 'datum'))
#model.setHeaderData(0, Qt.Horizontal, "ID")
model.select()
# Setup the view
# Create the view = a table widget
presentation_model = MyTableModel(model)
view = QTableView(self)
# Set the data model for table widget
#view.setModel(model)
view.setModel(presentation_model)
# Adjust column widths to their content
view.resizeColumnsToContents()
# Add the widget to main window
self.setCentralWidget(view)
# Type hint for return value
def createConnection() -> bool:
# SQLite type database connection instance
con = QSqlDatabase.addDatabase('QSQLITE')
# Connect to the database file
con.setDatabaseName('havana.sqlite3')
# Show message box when there is a connection issue
if not con.open():
QMessageBox.critical(
None,
'QTableView Example - Error!',
'Database Error: %s' % con.lastError().databaseText(),
)
return False
return True
if __name__ == "__main__":
app = QApplication(sys.argv)
if not createConnection():
sys.exit(1)
form = MainWindow()
form.show()
app.exec()
Thanks in advance
The "object is not subscriptable" error means that you're trying to access an item or index for an object that doesn't provide such interface.
>>> obj = 100
>>> print(obj[2])
TypeError: 'int' object is not subscriptable
self._model[index.row()][index.column()]
cannot work because Qt models are not lists or arrays, you cannot get their contents using square brackets.
In the same way, you cannot write values as you would do with a list with the same notation. You must use setData()
in the same way you're seeing in your implementation: by providing an index for that model and a value.
def setData(self, index, value, role):
if not index.isValid():
return False
if role == Qt.EditRole:
targetIndex = self._model.index(index.row(), index.column())
if self._model.setData(targetIndex, value, role):
self.dataChanged.emit(index, index)
return True
return False