PySide6使用QSqlRelationalTableModel插PostgreSQL行外键为空如何解决
问题根因
你遇到的插入失败问题核心是QSqlRelationalTableModel对关联外键字段的赋值逻辑和普通字段不同:直接通过record.setValue给关联的外键字段传整数值时,模型会将其识别为关联表的显示字段值而非外键存储值,自动丢弃传入的整数导致外键字段为NULL。
此外你当前代码中直接取self.ui.currency.currentIndex()作为currencyid是错误的,该值是下拉框的行序号,不是currency表对应的主键ID。
修正步骤
1. 修正currency下拉框的数值绑定
先在__init__方法中填充下拉框时,将每个选项对应的currency主键ID绑定到下拉框的itemData中,示例代码如下:
# 放在__init__方法中model初始化完成之后 currency_model = QSqlTableModel(self) currency_model.setTable("currency") currency_model.select() for i in range(currency_model.rowCount()): cur_id = currency_model.record(i).value("id") cur_type = currency_model.record(i).value("type") self.ui.currency.addItem(cur_type, cur_id)
2. 重写插入逻辑,改用行插入+逐字段赋值的方式
不要使用insertRecord方法,改为先插入空行再通过setData赋值的方式,适配QSqlRelationalTableModel的关联字段赋值规则,修改后的onadd方法如下:
def onadd(self): # 插入新空行 new_row = self.model.rowCount() if not self.model.insertRow(new_row): print("插入行失败:", self.model.lastError().text()) return # 逐字段赋值,列号和你model定义的顺序对应即可 self.model.setData(self.model.index(new_row, 1), self.ui.accname.text()) # 取下拉框绑定的currency主键ID,不是currentIndex self.model.setData(self.model.index(new_row, 2), self.ui.currency.currentData()) self.model.setData(self.model.index(new_row, 4), self.userid) # 提交行修改,匹配你设置的OnRowChange编辑策略 if not self.model.submitAll(): print("提交失败:", self.model.lastError().text()) self.model.revertRow(new_row) return # 提交成功后刷新模型 self.model.select()
可选兼容方案
如果一定要保留record的写法,需要在赋值后手动开启外键字段的生成标记:
def onadd(self): r = self.model.record() r.setGenerated("id",False) r.setGenerated("created",False) r.setGenerated("closed",False) r.setValue("name",self.ui.accname.text()) r.setValue("currencyid",self.ui.currency.currentData()) r.setValue("createdby",self.userid) # 手动开启两个外键字段的生成标记 r.setGenerated("currencyid", True) r.setGenerated("createdby", True) if not self.model.insertRecord(-1,r): print("插入失败:", self.model.lastError().text()) return self.model.select()
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

