Retrieve underlying data object from QAbstractTableModel

Heads up! You've already completed this tutorial.

Paul_B_Hermans | 2020-11-12 03:09:01 UTC | #1

I am struggling with pyqt5 and hoping someone can guide me a bit. I have a class called Student. I want to display a few QTableView (read only) with only 3 columns that shows first_name, last_name and section.

Then, when the user selects 1 or more rows in the tableview and presses a button, I want to get the Student object that was used to create that row, and then use some of its other properties to do stuff.

My problem is that I can't figure out how to get back to the actual Student object that was used to build the table. Here is some snippets of code I have.....hoping someone can clue me in.

python
class Student:
    def __init__(self, section, last_name, first_name, email, sn_folder):
        self.section = section
        self.last_name = last_name
        self.first_name = first_name
        self.email = email
        self.SN_Folder = sn_folder

    def __str__(self):
        return self.full_name()

    def __repr__(self):
        return self.__str__()

    def full_name(self):
        return self.last_name + ", " + self.first_name


class StudentTableModel(QtCore.QAbstractTableModel):

    # students is a list of Student objects.
    def __init__(self, students=None, parent=None):
        super().__init__(parent)

        if students is None:
            self.students = []
        else:
            self.students = students

    def rowCount(self, index=QtCore.QModelIndex()):
        """ Returns the number of rows the model holds. """
        return len(self.students)

    def columnCount(self, index=QtCore.QModelIndex()):
        """ Returns the number of columns the model holds. """
        return 5

    def data(self, index, role=QtCore.Qt.DisplayRole):
        """ Depending on the index and role given, return data. If not
            returning data, return None (PySide equivalent of QT's
            "invalid QVariant").
        """
        if not index.isValid():
            return None

        if not 0 <= index.row() < len(self.students):
            return None

        if role == QtCore.Qt.DisplayRole:
            last_name = self.students[index.row()].last_name
            first_name = self.students[index.row()].first_name
            section = self.students[index.row()].section
            email = self.students[index.row()].email
            sn_folder = self.students[index.row()].SN_Folder

            if index.column() == 0:
                return last_name
            elif index.column() == 1:
                return first_name
            elif index.column() == 2:
                return section
            elif index.column() == 3:
                return email
            elif index.column() == 4:
                return sn_folder
        return None

then in my mainwindow I have a method for the button being clicked:

python
    def go_clicked(self):
        # Get a list of Student Objects ( was used to build the table)
        students = self.selected_course().students

        # Get selected row indices from the tableview
        row_indexes=[]
        for row in self.tblStudents2.selectionModel().selectedRows():
            row_indexes.append(row.row())

        # Attempt to retrieve the actual Student Object that corresponds to the row in the table
        # - this is wrong but it illustrates the idea. It works if I don't allow table to be sorted.
        for index in row_indexes:
            student = students[index]
            print(student)

Thanks in advance for any help you can provide!


Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Retrieve underlying data object from QAbstractTableModel was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt.