PyQt5编程(43)—使用数据库(9)

4.2 与表格关联的模型
如果要编辑数据库中的数据,城使用QSqlTableModel类。 QSqlTableModel类的继承层次如下: 
QObject - QAbstractltemModel - QAbstractTableModel - QSqlQueryModel - QSqlTableModel
QSqlTableModel类的构造函数为:
QSqlTableModel([QObject parent = Q_NULLPTR][, QSqlDatabase db = QSqlDatabase()]):创建一个父类为parent的QSqlTableModel实例,并将数据库连接设置为db。 如果db无效,将使用默认的数据库连接。
QSqlTableModel类继承了QSqlQueryModel类中的所有方法,除此之外,还定义了以下方法(详见http://doc.qt.io/qt-5/qsqltablemodel.html):

setTable(QString tableName): 设置呈现在模型中的数据库中的tableName表。该方法只是读取表结构信息,并不包括数据。
tableName():呈现在模型中的数据库表名。
setSort(int column, Qt.SortOrder order): 设置数据按column进行order方式排序。
setFilter( QString filter):设置过滤器为filter.过滤器是一个没有关键字WHERE的SQL WHERE子句,例如:name='Josephine'
filter():返回过滤器。
select(): 根据排序方式、过滤器,将数据填充到表格中。
setEditStrategy(EditStrategy strategy):设置编辑策略。EditStrategy枚举变量有下列值:
    OnFieldChange:模型的所有更改将立即作用于数据库。
    OnRowChange:当切换到其他行时,模型的更改作用于数据库。
    OnManualSubmit:模型中的理改先缓存,仅调用submitAll()或 revertAll()后,才作用于数据库。
insertRow(int row[, QModelIndex  parent= QModelIndex()]): 在row条记录前增加一条。
insertRows(int row,int count,[, QModelIndex  parent= QModelIndex()]): 在row条记录前增加count条记录。
setData(QModelIndex index, const QVariant value, int role = Qt.EditRole):设置index索引的值为value.
removeRow(int row[, QModelIndex parent = QModelIndex()]):删除第row条记录。
removeRows(int row,int count[, QModelIndex parent = QModelIndex()]):删除第row条开始的count条记录。

 注意:
通过调用removeRow( )或removeRows( )方法删除条目后,将在模型中留下空记录,但并不代表数据库表中的任何记录,所以需要调用selec()方法重新读取模型中的数据来删除model中的空记录。

insertRecord(int row, QSqlRecord record):在row位置插入记录record.如果,row为-1,表示在末尾插入。
setRecord(int row, QSqlRecord values):将模型中row行的内容用values取代。 源和目标字段是按字段名称映射,而不是按记录中的位置。
submit(): 如果设置了OnManualSubmit编辑模式,则将当前记录中所做的更改作用于数据库。 
submitAll(): 如果设置了OnManualSubmit编辑模式,则将模型中所有修改的记录作用于数据库。 
revert():如果设置了OnManualSubmit编辑模式,则取消当前记录中所做的更改。
revertRow(int row):如果设置了OnManualSubmit编辑模式,则取消对row条记录所做的更改。
revertAll():如果设置了OnManualSubmit编辑模式,则取消对所有记录所做的更改。
selectRow(int row):使用数据库表row行的值刷新模型中的对应行。
isDirty([QModelIndex index]):如果模型index中有尚未提交到数据库的修改值,则返回True,否则返回False。
fieldIndex(QString fieldName): 返回fieldName字段的索引;
primaryKey():返回代表主键的一个QSqlIndex实例。

insertRecord()和setRecord()的第二个参数为QSqlRecord实例,QSqlRecord类的构造函数为:
QSqlRecord(QSqlRecord other)
 如果带参数,则是创建other的副本。通常是通过调用QSqlDatabase类的record()返回一个 QSqlRecord实例。当编辑已有记录时,则是调用QSqlTableModel类的record(),返回一个代表当前记录的QSqlRecord实例。
QSqlRecord类除了“PyQt5编程(37)”中提到的方法外,还有以下方法:

value(int index):返回当前记录的index字段的值。
value(Qstring fieldname):返回当前记录的fieldname字段的值。
setValue(int index, QVariant val):将当前记录的index字段的值设置为val。
setValue(QString name, const QVariant val):将当前记录的fieldname字段的值设置为val。
isNull(int index): 如果当前记录中index字段值为空值,返回True;否则返回False。
isNull(QString name):如果当前记录中name字段值为空值,返回True;否则返回False。
setNull(int index): 设置当前记录中index字段值为空值。
setNull(QString name):设置当前记录中name字段值为空值。
clearValues():清除记录中所有字段的值,并将每个字段设置为空。
setGenerated(int index, bool generated):将index字段的生成标志(generated flag)置位。
setGenerated(QString name, bool generated):将name字段的生成标志(generated flag)置位。
isGenerated(int index, bool generated):返回index字段的生成标志(generated flag)。
isGenerated(QString name, bool generated):返回name字段的生成标志(generated flag)。

添加记录到模型的示例代码:

con = QtSql.QSqlDatabase.addDatabase ('QSQLITE')
con.setDatabaseName ('data.sqlite')
con.open ()
stm = QtSql.QSqlTableModel ()
stm.setTable ('good')
stm.select ()
rec = con.record ('good')
rec.setValue ('goodname', 'Mouse pad')
rec.setValue ('goodcount', 3)
stm.insertRecord (-1, rec)

修改现有记录3的示例代码:
rec = stm.record(3)
rec.setValue('goodcount', 5)
stm.setRecord(3, rec)

QSqlTableModel类有以下信号:

primeInsert(int row, QSqlRecord record):在当前活动数据库表的给定行中时,insertRows()触发。
beforeInsert(QSqlRecord record):在当前活动数据库表中插入数据时,由insertRowIntoTable()触发。
beforeUpdate(int row, QSqlRecord record):在row行记录更新前,由updateRowInTable()触发。
beforeDelete(int row):在删除row行数据之前,由deleteRowFromTable()触发。
dataChanged(QModelIndex topLeft, QModelIndex bottomRight[, QVector roles = QVector ()]): 模型中的数据变化时触发。如果受影响的数据属同一父类,其区域为topleft到bottomright。可选的roles参数用于指定哪些数据实际上已被修改, 该参数为空, 意味着所有数据都已修改。

如果模型为OnManualSubmit编辑模式,那么dataChanged信号是调用submit()或submitAll()方法的理想场所。下列为数据库操作的相关代码,它不仅可以编辑,还可以通过按下相应的按钮来添加和删除记录。

from PyQt5 import QtCore, QtWidgets, QtSql
import sys

def addRecord ():
# 插入空记录,用户可手动输入
stm.insertRow (stm.rowCount ())

def delRecord ():
# 从模型中删除记录
stm.removeRow (tv.currentIndex (). row ())
# 重新加载数据到模型中
stm.select ()

app = QtWidgets.QApplication (sys.argv)
window = QtWidgets.QWidget ()
window.setWindowTitle ("QSqlTableModel")

Establish a connection to the database

con = QtSql.QSqlDatabase.addDatabase ('QSQLITE')
con.setDatabaseName ('data.sqlite')
con.open ()

Create a model

stm = QtSql.QSqlTableModel (parent = window)
stm.setTable ('good')
stm.setSort (1, QtCore.Qt.AscendingOrder)
stm.select ()

Set the headers for the columns of the model

stm.setHeaderData (1, QtCore.Qt.Horizontal, 'Name')
stm.setHeaderData (2, QtCore.Qt.Horizontal, 'Qty')

Set the table just created for the table

vbox = QtWidgets.QVBoxLayout ()
tv = QtWidgets.QTableView ()
tv.setModel (stm)

隐藏第一列

tv.hideColumn (0)
tv.setColumnWidth (1, 150)
tv.setColumnWidth (2, 60)
vbox.addWidget (tv)
btnAdd = QtWidgets.QPushButton ("添加记录(&A)")
btnAdd.clicked.connect (addRecord)
vbox.addWidget (btnAdd)
btnDel = QtWidgets.QPushButton ("删除记录(&A")
btnDel.clicked.connect (delRecord)
vbox.addWidget (btnDel)
window.setLayout (vbox)
window.resize (300, 250)
window.show ()
sys.exit (app.exec_ ())
<wbr> <wbr> 4.2 与表格关联的模型

<wbr> <wbr> 如果要编辑数据库中的数据,城使用QSqlTableModel类。 <wbr>QSqlTableModel类的

继承层次如下: <wbr>

<font face="Microsoft YaHei, Helvetica Neue, SimSun" color="#494949"> <wbr> <wbr> <wbr></font>QObject - QAbstractltemModel - QAbstractTableModel - QSqlQueryModel - QSqlTableModel

<wbr> <wbr> QSqlTableModel类的构造函数为:

<wbr> <wbr> QSqlTableModel([QObject parent = Q_NULLPTR][, QSqlDatabase db = QSqlDatabase()]):创建一个父类为parent的QSqlTableModel实例,并将数据库连接设置为db。 如果db无效,将使用默认的数据库连接。

<wbr> <wbr> <wbr>QSqlTableModel类继承了QSqlQueryModel类中的所有方法,除此之外,还定义了以下方法(详见http://doc.qt.io/qt-5/qsqltablemodel.html):

  • setTable(QString tableName): 设置呈现在模型中的数据库中的tableName表。该方法只是读取表结构信息,并不包括数据。
  • tableName():呈现在模型中的数据库表名。
  • setSort(int column, Qt.SortOrder order): 设置数据按column进行order方式排序。
  • setFilter( <wbr>QString filter):设置过滤器为filter.过滤器是一个没有关键字WHERE的SQL WHERE子句,例如:name='Josephine'
  • filter():返回过滤器。
  • select(): 根据排序方式、过滤器,将数据填充到表格中。
  • setEditStrategy(EditStrategy strategy):设置编辑策略。EditStrategy枚举变量有下列值:
    • OnFieldChange:模型的所有更改将立即作用于数据库。
    • OnRowChange:当切换到其他行时,模型的更改作用于数据库。
    • OnManualSubmit:模型中的理改先缓存,仅调用submitAll()或 revertAll()后,才作用于数据库。
  • insertRow(int row[, QModelIndex <wbr>parent= QModelIndex()]): 在row条记录前增加一条。
  • insertRows(int row,int count,[, QModelIndex <wbr>parent= QModelIndex()]): 在row条记录前增加count条记录。
  • setData(QModelIndex index, const QVariant value, int role = Qt.EditRole):设置index索引的值为value.
  • removeRow(int row[, QModelIndex parent = QModelIndex()]):删除第row条记录。
  • removeRows(int row,int count[, QModelIndex parent = QModelIndex()]):删除第row条开始的count条记录。

<font color="#FF0000"> <wbr> <wbr> <wbr>注意:</font>

<wbr> <wbr> 通过调用removeRow( )或removeRows( )方法删除条目后,将在模型中留下空记录,但并不代表数据库表中的任何记录,所以需要调用selec()方法重新读取模型中的数据来删除model中的空记录。

  • insertRecord(int row, QSqlRecord record):在row位置插入记录record.如果,row为-1,表示在末尾插入。
  • setRecord(int row, QSqlRecord values):将模型中row行的内容用values取代。 源和目标字段是按字段名称映射,而不是按记录中的位置。
  • submit(): <wbr>如果设置了OnManualSubmit编辑模式,则将当前记录中所做的更改作用于数据库。 <wbr>
  • submitAll(): <wbr>如果设置了OnManualSubmit编辑模式,则将模型中所有修改的记录作用于数据库。 <wbr>
  • revert():如果设置了OnManualSubmit编辑模式,则取消当前记录中所做的更改。
  • revertRow(int row):如果设置了OnManualSubmit编辑模式,则取消对row条记录所做的更改。
  • revertAll():如果设置了OnManualSubmit编辑模式,则取消对所有记录所做的更改。
  • selectRow(int row):使用数据库表row行的值刷新模型中的对应行。
  • isDirty([QModelIndex index]):如果模型index中有尚未提交到数据库的修改值,则返回True,否则返回False。
  • fieldIndex(QString fieldName): 返回fieldName字段的索引;
  • primaryKey():返回代表主键的一个QSqlIndex实例。

<wbr> <wbr> insertRecord()和setRecord()的第二个参数为QSqlRecord实例,QSqlRecord类的构造函数为:
<wbr> <wbr> <wbr>QSqlRecord(QSqlRecord other)
<wbr> <wbr> <wbr>如果带参数,则是创建other的副本。通常是通过调用QSqlDatabase类的record()返回一个 QSqlRecord实例。当编辑已有记录时,则是调用QSqlTableModel类的record(),返回一个代表当前记录的QSqlRecord实例。

<wbr> <wbr> QSqlRecord类除了“PyQt5编程(37)”中提到的方法外,还有以下方法:

  • value(int index):返回当前记录的index字段的值。
  • value(Qstring fieldname):返回当前记录的fieldname字段的值。
  • setValue(int index, QVariant val):将当前记录的index字段的值设置为val。
  • setValue(QString name, const QVariant val):将当前记录的fieldname字段的值设置为val。
  • isNull(int index): 如果当前记录中index字段值为空值,返回True;否则返回False。
  • isNull(QString name):如果当前记录中name字段值为空值,返回True;否则返回False。
  • setNull(int index): 设置当前记录中index字段值为空值。
  • setNull(QString name):设置当前记录中name字段值为空值。
  • clearValues():清除记录中所有字段的值,并将每个字段设置为空。
  • setGenerated(int index, bool generated):将index字段的生成标志(generated flag)置位。
  • setGenerated(QString name, bool generated):将name字段的生成标志(generated flag)置位。
  • isGenerated(int index, bool generated):返回index字段的生成标志(generated flag)。
  • isGenerated(QString name, bool generated):返回name字段的生成标志(generated flag)。

<wbr> <wbr> 添加记录到模型的示例代码:

con = QtSql.QSqlDatabase.addDatabase ('QSQLITE')

con.setDatabaseName ('data.sqlite')

con.open ()

stm = QtSql.QSqlTableModel ()

stm.setTable ('good')

stm.select ()

rec = con.record ('good')

rec.setValue ('goodname', 'Mouse pad')

rec.setValue ('goodcount', 3)

stm.insertRecord (-1, rec)

修改现有记录3的示例代码:

rec = stm.record(3)

rec.setValue('goodcount', 5)

stm.setRecord(3, rec)

QSqlTableModel类有以下信号:

  • primeInsert(int row, QSqlRecord record):在当前活动数据库表的给定行中时,insertRows()触发。
  • beforeInsert(QSqlRecord record):在当前活动数据库表中插入数据时,由insertRowIntoTable()触发。
  • beforeUpdate(int row, QSqlRecord record):在row行记录更新前,由updateRowInTable()触发。
  • beforeDelete(int row):在删除row行数据之前,由deleteRowFromTable()触发。
  • dataChanged(QModelIndex topLeft, QModelIndex bottomRight[, QVector roles = QVector ()]): 模型中的数据变化时触发。如果受影响的数据属同一父类,其区域为topleft到bottomright。可选的roles参数用于指定哪些数据实际上已被修改, 该参数为空, 意味着所有数据都已修改。

<wbr> <wbr> <wbr>如果模型为OnManualSubmit编辑模式,那么dataChanged信号是调用submit()或submitAll()方法的理想场所。下列为数据库操作的相关代码,它不仅可以编辑,还可以通过按下相应的按钮来添加和删除记录。

from PyQt5 import QtCore, QtWidgets, QtSql

import sys

def addRecord ():

<wbr> <wbr> # 插入空记录,用户可手动输入 <wbr>

<wbr> <wbr> stm.insertRow (stm.rowCount ())

def delRecord ():

<wbr> <wbr> # 从模型中删除记录

<wbr> <wbr> stm.removeRow (tv.currentIndex (). row ())

<wbr> <wbr> # 重新加载数据到模型中

<wbr> <wbr> stm.select ()

app = QtWidgets.QApplication (sys.argv)

window = QtWidgets.QWidget ()

window.setWindowTitle ("QSqlTableModel")

Establish a connection to the database

con = QtSql.QSqlDatabase.addDatabase ('QSQLITE')

con.setDatabaseName ('data.sqlite')

con.open ()

Create a model

stm = QtSql.QSqlTableModel (parent = window)

stm.setTable ('good')

stm.setSort (1, QtCore.Qt.AscendingOrder)

stm.select ()

Set the headers for the columns of the model

stm.setHeaderData (1, QtCore.Qt.Horizontal, 'Name')

stm.setHeaderData (2, QtCore.Qt.Horizontal, 'Qty')

Set the table just created for the table

vbox = QtWidgets.QVBoxLayout ()

tv = QtWidgets.QTableView ()

tv.setModel (stm)

隐藏第一列

tv.hideColumn (0)

tv.setColumnWidth (1, 150)

tv.setColumnWidth (2, 60)

vbox.addWidget (tv)

btnAdd = QtWidgets.QPushButton ("添加记录(&A)")

btnAdd.clicked.connect (addRecord)

vbox.addWidget (btnAdd)

btnDel = QtWidgets.QPushButton ("删除记录(&A")

btnDel.clicked.connect (delRecord)

vbox.addWidget (btnDel)

window.setLayout (vbox)

window.resize (300, 250)

window.show ()

sys.exit (app.exec_ ())

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容