vezzon vezzon - 1 year ago 105
Python Question

How to format a column with decimal numbers in QSqlTableModel

I have got a QSqlTableModel with decimal numbers in one column. How can I format this column to have numbers with 4 decimal places (e.g.: 2,3 --> 2,3000; 4,567891 --> 4,5679). I am using pyqt5.

Edit:

I tried to subclass QSqlTableModel like this:

class AlignmentTable(QSqlTableModel):
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole and index.column() == 4:
value = '{:01.4f}'.format(self.data(index))
return value


But I get the error: RecursionError: maximum recursion depth exceeded in comparison


  1. Edit:



First I load the model like this:

def load_sitesizes(self):

self.mod_site_sizes = AlignmentTable(parent=None, db=dbtools.ProjectDB.use_project_db(self))
self.mod_site_sizes.setTable("vSiteSizes")

site_id = str(self.item_id)
self.mod_site_sizes.setFilter("SiteKey='"+site_id+"'")

self.mod_site_sizes.select()

self.mod_site_sizes.setEditStrategy(QSqlTableModel.OnFieldChange)

self.tblSiteSizes.setModel(self.mod_site_sizes)


and than your code in a subclass:

class AlignmentTable(QSqlTableModel):

def data(self, item, role):

if role == Qt.DisplayRole:
if item.column() == 4:
val = QSqlTableModel.data(self, item, Qt.DisplayRole)
if not isinstance(val, float):
val = float(val)
return '{:.4f}'.format(round(val, 4))

Answer Source

You should not access the self.data(item) function since you are calling the same function, you must access through the parent: QSqlTableModel.data(self, item, Qt.DisplayRole).

period:

def data(self, item, role):
    if role == Qt.DisplayRole:
        if item.column() == 4:
            val = QSqlTableModel.data(self, item, Qt.DisplayRole)
            if not isinstance(val, float):
                val = float(val)
            return '{:.4f}'.format(round(val, 4))

commas:

def data(self, item, role):
    if role == Qt.DisplayRole:
        if item.column() == 4:
            number = round(float(QSqlTableModel.data(self, item, Qt.DisplayRole).replace(",", ".")),4)
            return ('{:.4f}'.format(number)).replace(".", ",")
    return QSqlTableModel.data(self, item, role)

According to what I observe in your database, the field of column 4 is of decimal type and the problem is that pyqt recognizes it as integer, the solution is simple, you must convert it to floating:

class CustomSqlModel(QSqlTableModel):
    def __init__(self, parent=None):
        QSqlTableModel.__init__(self, parent=parent)
        self.setTable("SiteSizes")
        self.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.select()

    def data(self, item, role):
        val = QSqlTableModel.data(self, item, role)
        if role == Qt.DisplayRole:
            if item.column() == 4:
                try:
                    return '{:.4f}'.format(round(float(val), 4))
                except ValueError:
                    pass
        if role == Qt.EditRole:
            if item.column() == 4:
                try:
                    return float(val)
                except ValueError:
                    pass
        return val

if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    db = QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName("zzProjekt1.db")

    model = CustomSqlModel()

    view = QTableView()
    view.resizeColumnsToContents()
    view.setModel(model)
    view.setWindowTitle("Custom Model")

    view.show()

    sys.exit(app.exec_())

Note: Another thing I've noticed from your database is that vSiteSizes is not a Table, it's a View, and it's read-only, so you can not edit it.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download