You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QSqlTableModel.insertRecord()未按指定行参数插入记录问题

问题

使用QSqlTableModel的insertRecord方法插入记录时,传入row=-1可正常将记录追加到表末尾,但传入其他行号时,记录不会插入到指定位置,示例代码如下:

import sys
from PySide6.QtWidgets import (QApplication, QMainWindow, QTableView)
from PySide6.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery


class SQLTableModel(QSqlTableModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        query = QSqlQuery()
        query.exec(
            "CREATE TABLE table1"
            "(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
            "type TEXT)"
        )


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("SQLTableDatabase.sqlite")
        self.db.open()

        self.table_view = QTableView()
        self.model = SQLTableModel()
        self.table_view.setModel(self.model)
        self.model.setTable("table1")

        for i in range(4):
            record = self.model.record()
            record.setValue("type", str(i))
            self.model.insertRecord(-1, record)

        record = self.model.record()
        record.setValue("type", "TEST")
        self.model.insertRecord(2, record)  # 为何该记录未插入到第2行位置?
        self.model.select()

        self.setCentralWidget(self.table_view)


app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec())
原因

QSqlTableModel是关系型数据库的直接映射模型,关系型数据库的表本身没有内置的固定行顺序概念,数据在存储层的排列由数据库内部管理,和插入时传入的row参数没有关系。
insertRecord方法的row参数,只对模型内存里暂存的未提交行生效,一旦调用select()从数据库拉取全量数据,模型会按默认规则(通常是主键升序)排列返回结果,之前传入的非-1行号不会影响数据库的返回顺序,自然看不到插入到指定位置的效果。

解决方案

要实现记录插入到指定显示位置,有两种常用方案:

  • 持久化排序方案:在表中新增专门的排序字段(比如命名为sort_order,整数类型),插入记录到指定位置时,先将该位置及之后所有记录的sort_order值+1,再给新记录设置对应位置的sort_order值,之后给模型设置按该字段升序排序再调用select(),即可持久化保持指定排列顺序。
  • 临时显示排序方案:如果不需要把排序规则持久化到数据库,可以使用QSortFilterProxyModel作为代理层,在内存中调整行的显示顺序,不需要修改原有表结构。

以下是基于持久化排序方案修改后的可运行代码:

import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QApplication, QMainWindow, QTableView)
from PySide6.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery


class SQLTableModel(QSqlTableModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        query = QSqlQuery()
        # 新增sort_order字段存储排序值
        query.exec(
            "CREATE TABLE IF NOT EXISTS table1"
            "(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
            "type TEXT, sort_order INTEGER)"
        )

    def insert_row_at_position(self, row, record):
        # 先将指定位置及之后的记录排序值后移
        self.database().transaction()
        query = QSqlQuery()
        query.prepare("UPDATE table1 SET sort_order = sort_order + 1 WHERE sort_order >= ?")
        query.addBindValue(row)
        query.exec()
        # 给新记录设置对应排序值
        record.setValue("sort_order", row)
        res = self.insertRecord(-1, record)
        self.database().commit()
        # 按排序字段刷新数据
        self.setSort(self.fieldIndex("sort_order"), Qt.AscendingOrder)
        self.select()
        return res


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("SQLTableDatabase.sqlite")
        self.db.open()

        self.table_view = QTableView()
        self.model = SQLTableModel()
        self.table_view.setModel(self.model)
        self.model.setTable("table1")
        # 设置按sort_order字段升序排列
        self.model.setSort(self.model.fieldIndex("sort_order"), Qt.AscendingOrder)
        self.model.select()

        # 初始化插入4条测试数据
        for i in range(4):
            record = self.model.record()
            record.setValue("type", str(i))
            record.setValue("sort_order", i)
            self.model.insertRecord(-1, record)
        self.model.select()

        # 在第2行位置插入TEST记录
        record = self.model.record()
        record.setValue("type", "TEST")
        self.model.insert_row_at_position(2, record)

        self.setCentralWidget(self.table_view)


app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec())

内容的提问来源于stack exchange,提问作者amateur3057

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:39:18