17.2 pyqt连接SQLite数据库
一、pyqt连接SQLite数据库
1.连接数据库
-
使用QSqlDatabase类来连接数据库,使用数据库驱动(Driver)与不同的数据库进行交互
-
QSqlDatabase类中的常用方法:
-
案例
创建并打开一个到MySql数据库的连接
from PyQt5.QtSql import QSqlDatabase
#选择数据库
db=QSqlDatabase.addDatabase('QMYSQL')
#设置数据库
db.setHostName("192.168.55.110")
db.setDatabaseName("user")
db.setUserName("root")
db.setPassword("ctsi123")
#打开数据库
dbConn=db.open()
创建一个SQLite数据库的默认连接
from PyQt5.QtSql import QSqlDatabase
#选择数据库
db=QSqlDatabase.addDatabase('QSQLITE')
#设置数据库
db.setDatabaseName('./db/sports.db') #这个要提前自己创建好db文件夹,并且在创建表之后才出现数据库的标识
#打开数据库
dbConn=db.open()
- 案例
功能:创建数据库并插入数据
#操作SQite数据库->本地数据库
import sys
#1.导入需要的数据库包
from PyQt5.QtSql import QSqlDatabase,QSqlQuery
#2.定义数据库函数
def createDB():
# 3.不同数据库的接口,更换数据库只需要在这更换名称就可
db=QSqlDatabase.addDatabase('QSQLITE')
# 4.指定SQLite数据库的文件名(本地就是一个文件名,要是远程的,应该指定一个数据库名)
db.setDatabaseName('db/database.db') #注意目录地址
if not db.open():
print('无法建立数据库连接')
return False
# 5.创建sql语句对象
query=QSqlQuery()
# 6.创建表
query.exec('create table people(id int primary key,name varchar(10),address varchar(50))')
# 7.插入数据(有数据之后才会显示数据库)
query.exec('insert into people values(1,"李宁","沈阳")')
# 8.关闭数据库
db.close()
return True
if __name__ == '__main__':
# 9.调用函数
createDB()
效果图
2.数据库可视化工具
-
下载sqlitestudio
https://sqlitestudio.pl/ -
解压缩文件,直接运行exe
-
运行之后的结果:
-
连接数据库
-
操作数据库
3.执行SQL语句
- 执行sql语句相关代码
query=QSqlQuery()
query.exec('create table people(id int primary key,name varchar(10),address varchar(50))')
- 注意事项:
必须执行关闭数据库的操作:db.close()
窗口关闭时,断开与数据库的连接,要重载closeEvent()事件
# 17——2——1
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSql import QSqlDatabase
class ExecDatabaseDemo(QWidget) :
def __init__(self, parent=None) :
super(ExecDatabaseDemo, self).__init__(parent)
#选择数据库
self.db = QSqlDatabase.addDatabase('QSQLITE')
#存放数据库
self.db.setDatabaseName('db/database.db')
# 打开数据库
self.db.open()
print('打开数据库')
def closeEvent(self, event) :
# 关闭数据库
self.db.close()
print('关闭数据库')
if __name__ == '__main__' :
app = QApplication(sys.argv)
demo = ExecDatabaseDemo()
demo.show()
sys.exit(app.exec_())
3.数据库模型视图(对数据库进行增加和删除)
- QSqlTableModel 类是一个高级接口,提供了可读的数据模型,用于在单个表中读取和保存数据。
- 此模型用于填充QTableView对象
QSqlTableModel 类是一个可以读和写的表格模型
- 当连接到数据库后,使用setTable()函数设置要查询的表
- 使用setFilter()函数设置过滤器条件,这个过滤器条件与SQL查询语句中的where条件一样.
- 然后使用 select()函数执行查询
- 最后使用setEditStrategy()函数设置“编辑策略”,可设置的编辑策略
- 案例
实现对数据库的增加和删除
点击查看代码
#17-2-2
import sys
from PyQt5.Qt import *
#1.导入需要的数据库包
from PyQt5.QtSql import QSqlDatabase,QSqlQuery
# 1创建模型(初始表)
def initialModel(model):
model.setTable('people')# people被当作模型
model.setEditStrategy(QSqlTableModel.OnFieldChange) # 编辑策略
model.select()
model.setHeaderData(0,Qt.Horizontal,'ID')
model.setHeaderData(1,Qt.Horizontal,'姓名')
model.setHeaderData(2,Qt.Horizontal,'地址')
# 2 创建视图-显示数据
def createView(title,model):
view=QTableView() #窗口
view.setModel(model)
view.setWindowTitle(title)
return view
# 3 记录当前行
def findrow(i):
delrow=i.row()
print('del roe=%s'% str(delrow))
# 4 添加行
def addrow():
ret=model.insertRows(model.rowCount(),1)
print('insertRow=%s' %str(ret))
if __name__ == '__main__':
# 可视化数据,并实现增删改查
'''
使用可视化的方式对SQLite数据库进行增删改查操作
QTableView
QSqlTableModel
'''
app=QApplication(sys.argv)
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('db/database.db')
# 创建模型视图
model=QSqlTableModel()
#初始化
delrow=-1
# 将数据转载到模型里
initialModel(model)
#在view中展示数据
view=createView("展示数据",model)
view.clicked.connect(findrow)
#将view添加到布局内部
dlg=QDialog()
layout=QVBoxLayout()
layout.addWidget(view)
#添加元素
addBtn=QPushButton('添加一行')
addBtn.clicked.connect(addrow)
#删除元素
delBtn=QPushButton('删除一行')
delBtn.clicked.connect(lambda :model.removeRow(view.currentIndex().row()))
layout.addWidget(view)
layout.addWidget(addBtn)
layout.addWidget(delBtn)
dlg.setLayout(layout)
dlg.setWindowTitle("Database Demo")
dlg.resize(500,400)
dlg.show()
sys.exit(app.exec_())
效果:
4. 分页查询控件
- 案例
点击查看代码
# -*- coding: utf-8 -*-
#17-2-3
import sys
from PyQt5.Qt import *
from PyQt5.QtCore import Qt
from PyQt5.QtSql import QSqlDatabase, QSqlQueryModel, QSqlQuery
# 1 创建数据库
def createTableAndInit() :
# 添加数据库
db = QSqlDatabase.addDatabase('QSQLITE')
# 设置数据库名称
db.setDatabaseName('db/database.db')
# 判断是否打开
if not db.open() :
return False
# 声明数据库查询对象
query = QSqlQuery()
# 创建表
query.exec("create table student(id int primary key, name vchar, sex vchar, age int, deparment vchar)")
# 添加记录
query.exec("insert into student values(1,'张三1','男',20,'计算机')")
query.exec("insert into student values(2,'李四1','男',19,'经管')")
query.exec("insert into student values(3,'王五1','男',22,'机械')")
query.exec("insert into student values(4,'赵六1','男',21,'法律')")
query.exec("insert into student values(5,'小明1','男',20,'英语')")
query.exec("insert into student values(6,'小李1','女',19,'计算机')")
query.exec("insert into student values(7,'小张1','男',20,'机械')")
query.exec("insert into student values(8,'小刚1','男',19,'经管')")
query.exec("insert into student values(9,'张三2','男',21,'计算机')")
query.exec("insert into student values(10,'张三3','女',20,'法律')")
query.exec("insert into student values(11,'王五2','男',19,'经管')")
query.exec("insert into student values(12,'张三4','男',20,'计算机')")
query.exec("insert into student values(13,'小李2','男',20,'机械')")
query.exec("insert into student values(14,'李四2','女',19,'经管')")
query.exec("insert into student values(15,'赵六3','男',21,'英语')")
query.exec("insert into student values(16,'李四2','男',19,'法律')")
query.exec("insert into student values(17,'小张2','女',22,'经管')")
query.exec("insert into student values(18,'李四3','男',21,'英语')")
query.exec("insert into student values(19,'小李3','女',19,'法律')")
query.exec("insert into student values(20,'王五3','女',20,'机械')")
query.exec("insert into student values(21,'张三4','男',22,'计算机')")
query.exec("insert into student values(22,'小李2','男',20,'法律')")
query.exec("insert into student values(23,'张三5','男',19,'经管')")
query.exec("insert into student values(24,'小张3','女',20,'计算机')")
query.exec("insert into student values(25,'李四4','男',22,'英语')")
query.exec("insert into student values(26,'赵六2','男',20,'机械')")
query.exec("insert into student values(27,'小李3','女',19,'英语')")
query.exec("insert into student values(28,'王五4','男',21,'经管')")
db.close()
return True
# 2 分页查询(初始化)
class DataGrid(QWidget) :
#在__init__()函数中声明要用道德控件,比如提示数据表控件、标签、前一页、后一页、按钮
def __init__(self) :
super().__init__()
self.setWindowTitle("分页查询例子")
self.resize(750, 300)
# 查询模型
self.queryModel = None
# 数据表
self.tableView = None
# 总数页文本
self.totalPageLabel = None
# 当前页文本
self.currentPageLabel = None
# 转到页输入框
self.switchPageLineEdit = None
# 前一页按钮
self.prevButton = None
# 后一页按钮
self.nextButton = None
# 转到页按钮
self.switchPageButton = None
# 当前页
self.currentPage = 0
# 总页数
self.totalPage = 0
# 总记录数
self.totalRecrodCount = 0
# 每页显示记录数
self.PageRecordCount = 5
self.db = None
self.initUI()
def initUI(self) :
# 创建窗口
self.createWindow()
# 设置表格
self.setTableView()
# 信号槽连接
self.prevButton.clicked.connect(self.onPrevButtonClick)
self.nextButton.clicked.connect(self.onNextButtonClick)
self.switchPageButton.clicked.connect(self.onSwitchPageButtonClick)
def closeEvent(self, event) :
# 关闭数据库
self.db.close()
# 2.1 创建窗口
def createWindow(self) :
# 2.1.1 操作布局:第一部分 初始化前一页、后一页和跳转按钮控件以及相关的标签控件
operatorLayout = QHBoxLayout()
self.prevButton = QPushButton("前一页")
self.nextButton = QPushButton("后一页")
self.switchPageButton = QPushButton("Go")
self.switchPageLineEdit = QLineEdit()
self.switchPageLineEdit.setFixedWidth(60)
switchPage = QLabel("转到第")
page = QLabel("页")
operatorLayout.addWidget(self.prevButton)
operatorLayout.addWidget(self.nextButton)
operatorLayout.addWidget(switchPage)
operatorLayout.addWidget(self.switchPageLineEdit)
operatorLayout.addWidget(page)
operatorLayout.addWidget(self.switchPageButton)
operatorLayout.addWidget(QSplitter())
# 2.1.2 状态布局:第二部分 初始化显示学生信息的数据表控件
statusLayout = QHBoxLayout()
self.totalPageLabel = QLabel()
self.totalPageLabel.setFixedWidth(80)
self.currentPageLabel = QLabel()
self.currentPageLabel.setFixedWidth(100)
self.totalRecordLabel = QLabel()
self.totalRecordLabel.setFixedWidth(80)
statusLayout.addWidget(self.totalPageLabel)
statusLayout.addWidget(self.currentPageLabel)
statusLayout.addWidget(QSplitter())
statusLayout.addWidget(self.totalRecordLabel)
# 设置表格属性
self.tableView = QTableView()
# 表格宽度的自适应调整
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 2.1.3 创建界面:第三部分 创建分页控件的主窗口,在主窗口中添加第一部分的布局和第二部分表格控件
mainLayout = QVBoxLayout(self);
mainLayout.addLayout(operatorLayout);
mainLayout.addWidget(self.tableView);
mainLayout.addLayout(statusLayout);
self.setLayout(mainLayout)
# 3 设置表格:获取表格控件用到的数据
def setTableView(self) :
print('*** step2 SetTableView')
self.db = QSqlDatabase.addDatabase('QSQLITE')
# 设置数据库名称
self.db.setDatabaseName('db/database.db')
# 打开数据库
self.db.open()
# 声明查询模型
self.queryModel = QSqlQueryModel(self)
# 设置当前页
self.currentPage = 1;
# 得到总记录数
self.totalRecrodCount = self.getTotalRecordCount()
# 得到总页数
self.totalPage = self.getPageCount()
# 刷新状态
self.updateStatus()
# 设置总页数文本
self.setTotalPageLabel()
# 设置总记录数
self.setTotalRecordLabel()
# 记录查询
self.recordQuery(0)
# 设置模型
self.tableView.setModel(self.queryModel)
print('totalRecrodCount=' + str(self.totalRecrodCount))
print('totalPage=' + str(self.totalPage))
# 设置表格表头
self.queryModel.setHeaderData(0, Qt.Horizontal, "编号")
self.queryModel.setHeaderData(1, Qt.Horizontal, "姓名")
self.queryModel.setHeaderData(2, Qt.Horizontal, "性别")
self.queryModel.setHeaderData(3, Qt.Horizontal, "年龄")
self.queryModel.setHeaderData(4, Qt.Horizontal, "院系")
# 4.添加槽函数
# 4.1得到记录数
def getTotalRecordCount(self) :
self.queryModel.setQuery("select * from student")
rowCount = self.queryModel.rowCount()
print('rowCount=' + str(rowCount))
return rowCount
# 4.2得到页数
def getPageCount(self) :
if self.totalRecrodCount % self.PageRecordCount == 0 :
return (self.totalRecrodCount / self.PageRecordCount)
else :
return (self.totalRecrodCount / self.PageRecordCount + 1)
# 4.3记录查询
def recordQuery(self, limitIndex) :
szQuery = ("select * from student limit %d,%d" % (limitIndex, self.PageRecordCount))
print('query sql=' + szQuery)
self.queryModel.setQuery(szQuery)
# 4.4刷新状态
def updateStatus(self) :
szCurrentText = ("当前第%d页" % self.currentPage)
self.currentPageLabel.setText(szCurrentText)
# 设置按钮是否可用
if self.currentPage == 1 :
self.prevButton.setEnabled(False)
self.nextButton.setEnabled(True)
elif self.currentPage == self.totalPage :
self.prevButton.setEnabled(True)
self.nextButton.setEnabled(False)
else :
self.prevButton.setEnabled(True)
self.nextButton.setEnabled(True)
# 4.5设置总数页文本
def setTotalPageLabel(self) :
szPageCountText = ("总共%d页" % self.totalPage)
self.totalPageLabel.setText(szPageCountText)
# 4.6设置总记录数
def setTotalRecordLabel(self) :
szTotalRecordText = ("共%d条" % self.totalRecrodCount)
print('*** setTotalRecordLabel szTotalRecordText=' + szTotalRecordText)
self.totalRecordLabel.setText(szTotalRecordText)
# 4.7前一页按钮按下
def onPrevButtonClick(self) :
print('*** onPrevButtonClick ');
limitIndex = (self.currentPage - 2) * self.PageRecordCount
self.recordQuery(limitIndex)
self.currentPage -= 1
self.updateStatus()
# 4.8后一页按钮按下
def onNextButtonClick(self) :
print('*** onNextButtonClick ');
limitIndex = self.currentPage * self.PageRecordCount
self.recordQuery(limitIndex)
self.currentPage += 1
self.updateStatus()
# 4.9 转到页按钮按下(此部分有自己修改)
def onSwitchPageButtonClick(self) :
# 得到输入字符串
szText = self.switchPageLineEdit.text()
# 判断是否为数字
if szText.isnumeric()==False:
QMessageBox.information(self, "提示", "请输入数字")
return
# 是否为空
if szText == '' :
QMessageBox.information(self, "提示", "请输入跳转页面")
return
# 得到页数
pageIndex = int(szText)
# 判断是否有指定页
if pageIndex > self.totalPage or pageIndex < 1 :
QMessageBox.information(self, "提示", "没有指定的页面,请重新输入")
return
# 得到查询起始行号
limitIndex = (pageIndex - 1) * self.PageRecordCount
# 记录查询
self.recordQuery(limitIndex);
# 设置当前页
self.currentPage = pageIndex
# 刷新状态
self.updateStatus();
if __name__ == '__main__' :
app = QApplication(sys.argv)
if createTableAndInit() :
# 创建窗口
example = DataGrid()
# 显示窗口
example.show()
sys.exit(app.exec_())
- 运行效果