QSQL模型
除了 QSqlQuery,Qt中还提供了3个用于访问数据库的更高级别的类,分别为QSq1QueryModel、QSqlTableModel 和 QSqlRelationalTableModel。这3个类的结构关系如图所示,作用如表所示。
用SQL命令对数据库进行操作并不直观,PySide 提供了对数据库进行可视化操作的Model/View 结构,通过数据库模型读入在数据库中查询到的数据,并通过视图控件(如QTableView)显示数据库模型中的数据,通过代理控件在视图控件中对数据进行新增更新、删除等操作,再通过数据模型把操作后的数据保存到数据库中。
PySide 提供的数据库模型有 QSqlQueryModel、QSqlTableModel和 QSqlRelationalTableModel,它们之间的继承关系如图所示。
类 | 描 述 |
---|---|
QSqlQueryModel | 基于任意 SQL查询的只读模型 |
QSqITableModel | 适用于单个表的读/写模型 |
QSqIRelationaITableModel | 具有外键支持的QSqlTableModel 子类 |
查询模型QSqlQueryModel
QSqlQueryModel类为SQL结果集提供只读数据模型
数据库查询模型 QSlQueryModel 只能从数据库中读取数据,而不能修改数据,可以用视图控件,例如 QTableView 来显示查询模型 QSqlQueryModel 中的数据。
用QSglQueryModel 创建数据库查询模型对象的方法如下所示。
from PySide6.QtSql import QSqlQueryModel
QSqlQueryModel(parent: Union[PySide6.QtCore.QObject,NoneType] = None)-> None
查询模型QSqlQueryModel官方说明
QSqlQueryModel是一个高级接口,用于执行SQL语句和遍历结果集。它构建在较低级别的QSqlQuery之上,可用于为视图类(如QTableView)提供数据。例如:
model = QSqlQueryModel()
model.setQuery("SELECT name, salary FROM employee")
model.setHeaderData(0, Qt.Horizontal, tr("Name"))
model.setHeaderData(1, Qt.Horizontal, tr("Salary"))
view = QTableView()
view.setModel(model)
view.show()
我们设置了模型的查询,然后设置了视图标题中显示的标签。
QSqlQueryModel也可以用于以编程方式访问数据库,而无需将其绑定到视图:
model = QSqlQueryModel()
model.setQuery("SELECT name, salary FROM employee")
salary = model.record(4).value("salary").toInt()
上面的代码片段从SELECT查询的结果集中的记录4中提取了salary字段。由于工资是第二列(或列索引1),我们可以将最后一行重写如下:
salary = model.data(model.index(4, 1)).toInt()
默认情况下,该模型是只读的。要使其读写,必须对其进行子类化并重新实现setData()和flags()。另一种选择是使用QSqlTableModel,它提供了一个基于单个数据库表的读写模型。
querymodel示例说明了如何使用QSqlQueryModel来显示查询的结果。它还展示了如何在向用户显示数据之前对QSqlQueryModel进行子类化以自定义数据的内容,以及如何基于QSqlQueryModel创建读写模型。
如果数据库没有返回查询中所选行的数量,则模型将递增地获取行。有关详细信息,请参阅fetchMore()。
查询模型 QSqlQueryModel 的常用方法
数据库查询模型 QSqlQueryModel的常用方法如表所示主要方法
- 用setQuery(query:QSqlQuery)方法或 setQuery(query:str,db;QSqlDatabase = Default(QSqlDatabase))方法设置数据库查询 QSqlQuery;
- 用setHeaderData(section: int,orientation:Qt.Orientation,value: Any,role: int=Qt.EditRole)方法设置显示数据的视图控件表头某角色的值
- 在 orientation 取 Qt.Horizontal,并且 section 取值合适时返回True,其他情况返回 False
- 其中 value 是某种角色的值,section 是列索引
QSqlQueryModel的方法及参数类型 | 返回值的类型 | 说明 |
---|---|---|
setQuery(query:QSqlQuery) | None | 设置数据库查询 |
setQuery(query:str,db: QSqlDatabase= Default(QSqlDatabase)) | None | 设置数据库查询 |
query() | QSqlQuery | 获取数据查询 |
setHeaderData(section:int,orientation: Qt.Orientation,value: Any,role: int = Qt.EditRole) | bo01 | 设置显示数据的视图控件(如 QTableView)表头某角色的值 |
headerData(section: int,orientation: Qt.Orientation,role: int = Qt.ItemDataRole. DisplayRole) | Any | 获取显示数据的视图控件表头某种角 色的值 |
record() | QSqlRecord | 获取包含字段信息的空记录 |
record(row:int) | QSqlRecord | 获取指定的字段记录 |
rowCount(parent: QModelIndex= Invalid(QModelIndex)) | int | 获取数据表中记录(行)的数量 |
columnCount(parent:QModelIndex=Invalid(QModelIndex)) | int | 获取数据表中字段(列)的数量 |
clear() | None | 清空查询模型中的数据 |
查询模型QSqlQueryModel的应用实例
下面的程序用菜单打开前一节创建的 SQLite数据库文件 student score_new.db
用QTableView 控件显示出数据表中的数据用QComboBox控件显示数据库中的数据表名称在QComboBox中选择不同的数据表名称时QTableView 控件将同步显示该数据表中的数据
# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/12 23:23
# File_name: 03-数据库查询模型QSqlQueryModel的应用实例.py
from PySide6.QtWidgets import QApplication,QWidget,QComboBox,QTableView,QLabel,QHBoxLayout,QVBoxLayout,QFileDialog,QMenuBar
from PySide6.QtSql import QSqlDatabase,QSqlQueryModel
from PySide6.QtCore import Qt
import sys
class MyWidget(QWidget):
def __init__(self,parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
menuBar = QMenuBar()
fileMenu = menuBar.addMenu("文件(&F)")
fileMenu.addAction("打开(&0)").triggered.connect(self.actionOpen)
fileMenu.addSeparator()
fileMenu.addAction("关闭(&E)").triggered.connect(self.close)
label = QLabel("选择数据表:")
self.combox = QComboBox()
self.combox.currentTextChanged.connect(self.comboxTextChanged)
H = QHBoxLayout()
H.addWidget(label,stretch=0)
H.addWidget(self.combox,stretch=1)
self.tableView = QTableView()
self.tableView.setAlternatingRowColors(True)
V = QVBoxLayout(self)
V.addWidget(menuBar)
V.addLayout(H)
V.addWidget(self.tableView)
def actionOpen(self):
dbFile,fil = QFileDialog.getOpenFileName(self,dir=".",filter="SQLite(*.db *.db3)")
if dbFile:
self.setWindowTitle(dbFile)
self.combox.clear()
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName(dbFile)
self.sqlQueryModel = QSqlQueryModel(self)
if self.db.open(): # 数据库查询模型
tables = self.db.tables()
if len(tables)> 0:
self.combox.addItems(tables)
def comboxTextChanged(self,text):
self.sqlQueryModel.setQuery("SELECT * FROM {}".format(text),self.db)
header = self.sqlQueryModel.record()
for i in range(header.count()):
self.sqlQueryModel.setHeaderData(i,Qt.Orientation.Horizontal,header.fieldName(i),Qt.DisplayRole)
self.tableView.setModel(self.sqlQueryModel)# 设置表格视图的数据模型
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MyWidget()
win.show()
sys.exit(app.exec())