【发布时间】:2021-04-19 09:36:11
【问题描述】:
我有一个QTableView,它显示 SQLite 数据库中表的数据子集。该表只能对可为空的数值列进行编辑。我创建了两个代表 - 一个用于只读列:
class ReadOnlyDelegate(QtWidgets.QItemDelegate):
def editorEvent(self, *args, **kwargs):
return False
def createEditor(self, *args, **kwargs):
return None
还有一个用于可编辑列:
class LabelDelegate(QtWidgets.QItemDelegate):
def createEditor(self, parent, options, index):
self.le = QtWidgets.QLineEdit(parent)
return self.le
表格由自定义的QSqlTableModel 提供,我覆盖了 submitAll 方法:
class MySqlTableModel(QtSql.QSqlTableModel):
def submitAll(self):
for row in range(self.rowCount()):
for col in range(self.columnCount()):
if self.isDirty(self.index(row, col)):
val = self.record(row).value(col)
if val == '':
self.record(row).setNull(col)
else:
try:
self.record(row).setValue(col, float(val))
except (TypeError, ValueError):
display_error_msg('Can not convert to float',
f'The value {val} could not be converted to float')
raise
super().submitAll()
预期的行为是 (1) 在发送到数据库之前将值转换为浮点数,(2) 拒绝无法转换为浮点数的输入,以及 (3) 将空字符串转换为 NULL。 (1)和(2)按预期工作,但最后一位不起作用。在调试方法.submitAll() 时,它不会在self.record(row).setNull(col) 行上引发异常,但它似乎也没有效果。一个空字符串被发送并保存在数据库中。任何想法为什么以及如何解决它?
【问题讨论】:
-
QSqlTableModel.record 是
const。您需要使用setRecord。 -
我会试一试,但
self.record(row).setValue(col, float(val))有效。只是self.record(row).setNull(col)没有将值设置为NULL,而是一个空字符串。实际上,我错误地指出它似乎没有效果。它也可以,只需将值设置为空字符串。如果我通过删除数字条目来编辑记录,它将保留在数据库中,但作为空字符串而不是NULL。 -
这可能是 SQLite 特有的,因为它没有“真正的”数据类型。您可以将任何数据类型插入任何列。我在其他地方没有遇到这个问题,因为我正在使用 sqlalchemy 来解决这个问题。在其他后端,无法将字符串插入数字列。
-
我从不使用记录来设置值,所以我只是假设
setRcord是必要的,因为其他几个 Qt API 都是这样工作的。你试过setValue(col, None)吗? -
是的,但是结果和
setNull一模一样