【数据库实验】实验四 基于嵌入SQL的综合应用编程(基于QSqlTableModel实现)

一、实验目的

本次实验的主要目的是掌握嵌入SQL及主高级语言,学会使用嵌入SQL对数据库进行增、删、改、备份的方法。

二、实验要求

1.要求学生独立完成实验内容,画出E-R图及程序功能图;
2.按照实验步骤完成实验后,撰写报告内容,并对操作结果进行截图,写出主要关键程序代码。

三、实验内容、实验结果与主要程序代码

基于实验一的三个表采用嵌入式SQL语言及主语言编程实现数据库的录入、修改、删除和备份等管理功能,并能实现基于学号显示学生基本信息、课程名、成绩信息。
(一) 画出E-R图及程序功能分析设计图
(二)功能实现界面图及主要程序代码(要有注释)

数据准备(建表并插入数据)

在这里插入图片描述

前言:黎哥的写法

先使用QT写好.ui文件,然后使用pyuic转化为.py文件,在.py文件内,写槽函数,写连接函数写执行函数。使用pymysqlcursor游标,执行sql命令。显示数据。
备份的实现,使用了系统命令,具体实现如下所示。

name="root"
key="passwd"
path="D://xxxx/"
os.system("mysql drop -u {1} -p {2} {3} values(%,%,%)".(name,key,path))

参考

PyQt5教程 课时139 使用可视化的方式对SQLite数据库进行增、删、改、查操作
Qt数据库(5)-使用SQLModel类
qtableview add rows from a query and edit them in python

    self.model.setTable("produse")

    self.produse_view.setModel(self.model)
    self.produse_view.hideColumn(0) # hide id column
    self.addData(["a", "b", "c", "d", "e", "f"])

def addData(self, data):

    rec = self.model.record()

    for i in range(6):
        rec.setValue(rec.field(i+1).name(), data[i])
    self.model.insertRecord(-1, rec)

建表

#建立S学生表
Drop if exists S;
CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20));
#建立SC选课表
Drop if exists SC;
CREATE TABLE SC(sclass int,sno int,cno int ,grade int);
#建立C课程表
Drop if exists C;
CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int);

SQL语言插入数据

S表
INSERT INTO S VALUES(1,1,'李勇','男',20,'IS');
INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS');
INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS');
INSERT INTO S VALUES(2,1,'王敏','女',18,'MA');
INSERT INTO S VALUES(2,2,'张锋','男',19,'MA');
INSERT INTO S VALUES(2,3,'李敏','男',20,'MA');
SC表
INSERT INTO SC VALUES(1,1,1,92);
INSERT INTO SC VALUES(1,1,2,85);
INSERT INTO SC VALUES(1,1,3,88);
INSERT INTO SC VALUES(1,2,2,90);
INSERT INTO SC VALUES(1,2,3,80);
INSERT INTO SC VALUES(2,1,1,75);
INSERT INTO SC VALUES(2,1,2,92);
INSERT INTO SC VALUES(2,2,2,87);
INSERT INTO SC VALUES(2,2,3,89);
INSERT INTO SC VALUES(2,3,1,90);
C表
INSERT INTO C VALUES(1,'数据库',5,4);
INSERT INTO C VALUES(2,'数学',NULL,2);
INSERT INTO C VALUES(3,'信息系统',1,4);
INSERT INTO C VALUES(4,'操作系统',6,3);
INSERT INTO C VALUES(5,'数据结构',7,4);
INSERT INTO C VALUES(6,'数据处理',NULL,2);
INSERT INTO C VALUES(7,'PASCAL语言',6,4);

嵌入式SQL

S表
query.exec_	("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
query.exec_	("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
query.exec_	("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
query.exec_	("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
query.exec_	("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
query.exec_	("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")
SC表
query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
query.exec_("INSERT INTO SC VALUES(2,3,1,90)")
C表
query.exec_("INSERT INTO C VALUES(1,'数据库',5,4)")
query.exec_("INSERT INTO C VALUES(2,'数学',NULL,2)")
query.exec_("INSERT INTO C VALUES(3,'信息系统',1,4)")
query.exec_("INSERT INTO C VALUES(4,'操作系统',6,3)")
query.exec_("INSERT INTO C VALUES(5,'数据结构',7,4)")
query.exec_("INSERT INTO C VALUES(6,'数据处理',NULL,2)")
query.exec_("INSERT INTO C VALUES(7,'PASCAL语言',6,4)")

程序按钮组成

按实验要求,需要有基于学号的检索数据功能,插入数据功能,删除数据功能,以及备份数据库功能。
首先建立数据库一个按钮,
然后显示一个按钮,
然后查询一个按钮,
然后删除一个按钮,
然后修改一个按钮,
然后备份一个按钮,
最后退出一个按钮。

共计7个按钮。

在这里插入代码片

备份实现

SQLITE的备份保存实现

保存的本质是把当前sqlite文件进行另存为保存。
保存图片

from tkinter import *
fname = tkinter.filedialog.asksaveasfilename(title=u'保存文件', filetypes=[("PNG", ".png")])
picture.save(str(fname) + '.png', 'PNG')

只需要在弹出对话框后选择保存位置,输入图片名字即可。
【注】如果不加以下两行代码:

root = tkinter.Tk()    # 创建一个Tkinter.Tk()实例
root.withdraw()       # 将Tkinter.Tk()实例隐藏

程序运行后将会出现一个小框。

MYSQL数据库备份

对于其他数据库,比如MYSQL数据库来说:
使用Python3编写脚本一键备份MySQL数据库

使用的是subprocess

import logging
import os
import subprocess
import pymysql
  • 备份
    logging.info('开始备份数据库 {}...'.format(database))
    # 通过调用mysqldump完成指定数据库的备份
    command = 'mysqldump -h192.168.1.4 -uroot -p666 --add-drop-database --databases {database} > {backup_path}/{database}.sql'.format(
        database=database,
        backup_path=BACKUP_PATH)
    exit_code = subprocess.call(command, shell=True)
    # 判断命令是否正常执行,异常则直接抛出
    if exit_code != 0:
        raise Exception('在备份数据库的过程中出错,请检查!')
    logging.info('数据库 {} 备份完毕!'.format(database))
  • 恢复
import logging
import os
import subprocess
import pymysql

# 设置日志输出格式
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.INFO)
# MySQL数据库用户名
MYSQL_USERNAME = 'root'
# 数据库密码
MYSQL_PASSWORD = 'mypassword'
# 数据库主机地址
MYSQL_HOST = '192.168.1.4'
# 数据库端口
MYSQL_PORT = 3306
# 备份文件存放路径
BACKUP_PATH = 'backup'
logging.info('开始获取需要恢复的数据库文件...')
files = list(os.listdir(BACKUP_PATH))
logging.info('文件列表:{}'.format(files))
# 开始逐个恢复数据库
for file in files:
    logging.info('开始恢复数据库 {}...'.format(file.split('.')[0]))
    command = 'mysql -h{host} -f -u{user} -p{password} -P{port} < {path}/{file}'.format(host=MYSQL_HOST,                                                                                      user=MYSQL_USERNAME,                                                                            password=MYSQL_PASSWORD,                                                                           port=MYSQL_PORT, file=file,                                                                                path=BACKUP_PATH)
    subprocess.call(command, shell=True)
logging.info('完毕!')

主要代码

最简单的库引用的写法:

import sys 
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *

QSqlTableModel和QSqlQueryModel

QSqlQuery
可以用来执行SQL语句和获得执行结果的。
QSqlQueryModel
提供了一个sql查询结果的只读数据模型。它从查询QSqlQueryModel获取数据。
可以方便的用于在QListView, QTableView, QTreeView等各种view上展示数据。
但它是只读的,不能编辑。
QSqlTableMode
继承于QSqlQueryModel,与QSqlQueryModel功能相似。
比QSqlQueryModel的限制在于不能是任意sql语句,只是对单个数据表操作。
拓展在于在各种view上展示表格数据的同时,还允许用户进行编辑操作。

bool QSqlTableModel:: select ()
使用通过setTable ()设置的表中的数据填充模型,使用指定的过滤器(setFilter())和排序条件,true如果成功则返回;否则返回false。
注意:调用 select()将恢复任何未提交的更改并删除任何插入的列。
另请参见setTable ()setFilter ()selectStatement ()

界面

def __init__(self):
    super().__init__()
    self.initUi()

def initUi(self):
    # 设置窗口标题
    self.setWindowTitle("刘看日的数据库实验四")
    # 设置窗口大小
    self.resize(600, 400)

    # 创建一个窗口部件
    self.widget = QtWidgets.QWidget()
    # 创建一个网格布局
    self.grid_layout = QtWidgets.QGridLayout()
    # 设置窗口部件的布局为网格布局
    self.widget.setLayout(self.grid_layout)

    # 创建一个工具组
    self.group_box = QtWidgets.QGroupBox('功能按钮')
    self.group_box_layout = QtWidgets.QVBoxLayout()
    self.group_box.setLayout(self.group_box_layout)


    #设置一个LineEdit窗口
    self.text=QtWidgets.QLineEdit()
    # 设置文本框的默认浮现文本
    self.text.setPlaceholderText("输入学号/课程号")

    self.table_view = QtWidgets.QTableView()
    # 按钮控件设置
    self.btn_create=QPushButton("连接表")
    self.btn_showall=QPushButton("展示全部数据")
    self.btn_search = QPushButton("基于学号/课程号查询")
    self.btn_close = QPushButton("退出")
    self.btn_delete=QPushButton("删除")
    self.btn_edit=QPushButton("修改")
    self.btn_add=QPushButton("添加")
    self.btn_backup = QPushButton("备份")

    # 添加按钮到group_box大组件中
    self.group_box_layout.addWidget(self.text)
    self.group_box_layout.addWidget(self.btn_create)
    self.group_box_layout.addWidget(self.btn_showall)
    self.group_box_layout.addWidget(self.btn_search)
    self.group_box_layout.addWidget(self.btn_add)
    self.group_box_layout.addWidget(self.btn_delete)
    self.group_box_layout.addWidget(self.btn_edit)
    self.group_box_layout.addWidget(self.btn_backup)
    self.group_box_layout.addWidget(self.btn_close)

    # 将上述两个部件添加到网格布局中
    self.grid_layout.addWidget(self.table_view, 0, 0)  # 放置表格位置在0
    self.grid_layout.addWidget(self.group_box, 0, 1)  # 放置
    # 创建按钮功能按钮
    self.btn_create.clicked.connect(self.create_db)
    self.btn_showall.clicked.connect(self.showall_tab)
    self.btn_search.clicked.connect(self.search_data)
    self.btn_close.clicked.connect(self.close)
    self.btn_add.clicked.connect(self.add_row_data)
    self.btn_delete.clicked.connect(self.del_row_data)
    self.btn_edit.clicked.connect(self.edit_row_data)
    self.btn_backup.clicked.connect(self.backup_data)
    # 设置UI界面的核心部件
    self.setCentralWidget(self.widget)

创建数据库,插入数据表

def create_db(self):
    # 添加一个mysql数据库连接并打开
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')  # 创建Mysql数据库,可自定义
    if db.setDatabaseName('student.sqlite'):  # 设置数据库名称
        print("创建'student.sqlite'数据库文件成功")
        msgBox1 = QMessageBox()
        msgBox1.setText("创建'student.sqlite'数据库文件成功")
        msgBox1.exec()
    else:
        print("'student.sqlite'数据文件已经存在")
        msgBox2 = QMessageBox()
        msgBox2.setText("'student.sqlite'数据文件已经存在")
        msgBox2.exec()

    db.setHostName("127.0.0.1")#可以有多个连接到同一个数据库,也就是说连接名不唯一
    db.setUserName('tom')#定义用户名
    db.setPassword('tom@123')#定义密码

    # success!
    db.open()
    table_text, table_action = QtWidgets.QInputDialog.getText(self, '表名称', '请输入表名称', QtWidgets.QLineEdit.Normal)
    if (table_text.replace(' ', '') != '') and (table_action is True):
         print(table_text)
    #实例化一个查询对象
    self.tablename=table_text

    #先进行插入数据

    query = QtSql.QSqlQuery()
    if query.exec_("Drop table if exists s"):
        print("drop table s ok!")
    if query.exec_("CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20))"):
        print("create table s ok!")
    if query.exec_("Drop table if exists sc"):
        print("drop table sc ok!")
    if query.exec_("CREATE TABLE SC(sclass int,sno int,cno int ,grade int)"):
        print("create table sc ok!")
    if query.exec_("Drop table if exists c"):
        print("drop table c ok!")
    else:
        print("error:drop table c")
    if query.exec_("CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int)"):
        print("create table c ok!")
    else:
        print("error:create table c")

    query.exec_("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
    query.exec_("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
    query.exec_("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
    query.exec_("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
    query.exec_("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
    query.exec_("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")

    query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
    query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
    query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
    query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
    query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
    query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
    query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
    query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
    query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
    query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

    query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
    query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
    query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
    query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
    query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
    query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
    query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
    query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
    query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
    query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

    db.close()

展示表的全部数据

def showall_tab(self):
    query = QtSql.QSqlQuery()
    if (self.tablename == "s"):
        msgBox3 = QMessageBox()
        msgBox3.setText("展示表s")
        msgBox3.exec()

        self.model = QtSql.QSqlTableModel(
            self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        # model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

        self.model.setTable("s")
        self.model.select()
        self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

    elif (self.tablename == "sc"):
        msgBox4 = QMessageBox()
        msgBox4.setText("展示表sc")
        msgBox4.exec()

        self.model = QtSql.QSqlTableModel(
            self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        # model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')


        self.model.setTable("sc")
        self.model.select()
        self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

    elif (self.tablename == "c"):
        msgBox5 = QMessageBox()
        msgBox5.setText("展示表c")
        msgBox5.exec()

        self.model = QtSql.QSqlTableModel(self.table_view)
        # onfieldchange模型的任何更改都会返回到数据库
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '课程名')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '先修课')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '学分')


        self.model.setTable("c")
        self.model.select()
        self.table_view.setModel(self.model)

    else:
        msgBox6 = QMessageBox()
        msgBox6.setText("表暂且不属于实验范围,请更换!")
        msgBox6.exec_()

查找,添加,删除,修改

def search_data(self):
    query = QtSql.QSqlQuery()
    # 创建一个数据库表
    if(self.tablename=="s"):
        msgBox3 = QMessageBox()
        msgBox3.setText("查询表s")
        msgBox3.exec()

        self.model = QtSql.QSqlTableModel(self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        #model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

        search = self.text.text()
        self.model.setTable("s")
        self.model.setFilter("sno={}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

    elif(self.tablename=="sc"):
        msgBox4 = QMessageBox()
        msgBox4.setText("查询表sc")
        msgBox4.exec()

        self.model = QtSql.QSqlTableModel(self.table_view) # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        #model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')

        search = self.text.text()
        self.model.setTable("sc")
        self.model.setFilter("sno = {}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

    elif(self.tablename=="c"):
        msgBox5 = QMessageBox()
        msgBox5.setText("查询表c")
        msgBox5.exec()

        self.model=QtSql.QSqlTableModel(self.table_view)
        #onfieldchange模型的任何更改都会返回到数据库
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.setHeaderData(0,QtCore.Qt.Horizontal,'课程号')
        self.model.setHeaderData(1,QtCore.Qt.Horizontal,'课程名')
        self.model.setHeaderData(2,QtCore.Qt.Horizontal,'先修课')
        self.model.setHeaderData(3,QtCore.Qt.Horizontal,'学分')

        search=self.text.text()
        self.model.setTable("c")
        self.model.setFilter("cno = {}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)

    else:
        msgBox6=QMessageBox()
        msgBox6.setText("表暂且不属于实验范围,请更换!")
        msgBox6.exec_()

def add_row_data(self):
    #不是直接操作QTableView,而是对model模型进行添加
    # 如果存在实例化的数据模型对象
    # self.model.insertRow(self.model.rowCount(),1)

    if self.model:
        #rowCount()得到行数,然后添加一行
        self.model.insertRows(self.model.rowCount(), 1)
        self.model.submitAll()#提交修改
    else:
        self.create_db()

def del_row_data(self):
    if self.model:
        self.model.removeRow(self.table_view.currentIndex().row())
        self.model.submitAll()#提交修改
    else:
        self.create_db()

def edit_row_data(self):
    if self.model:
        self.model.submitAll()#提交更改
    else:
        self.create_db()

备份实现(文件函数)

def backup_data(self):
    ori_file_name = r'D:\coding_programs\PythonPrograms\database_exp4\student.sqlite'  # 输入文件路径
    if os.path.isfile(ori_file_name):  # 判断该路径的是否是文件
        # 截取文件名,重组文件名
        seek_num = ori_file_name.rfind('.')
        new_file_name = ori_file_name[:seek_num] + '.bak'
        # 打开源文件
        old_file = open(ori_file_name, 'rb')
        # 读取文件信息
        old_file_content = old_file.read()
        # 创建新文件
        new_file = open(new_file_name, 'wb')
        # 将原始文件信息写入
        new_file.write(old_file_content)
        # 关闭文件
        old_file.close()
        new_file.close()
        print("backup success!")
        msgBox7 = QMessageBox()
        msgBox7.setText("student.bak数据文件已经备份")
        msgBox7.exec()
    else:
        print('没有该文件')

演示GIF

在这里插入图片描述

完整代码

# coding:utf-8

import os,sys
from PyQt5 import QtCore, QtWidgets, QtSql
from PyQt5.QtWidgets import QApplication, QMessageBox, QPushButton

class MainUi(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUi()

    def create_db(self):
        # 添加一个mysql数据库连接并打开
        db = QtSql.QSqlDatabase.addDatabase('QSQLITE')  # 创建Mysql数据库,可自定义
        if db.setDatabaseName('student.sqlite'):  # 设置数据库名称
            print("创建'student.sqlite'数据库文件成功")
            msgBox1 = QMessageBox()
            msgBox1.setText("创建'student.sqlite'数据库文件成功")
            msgBox1.exec()
        else:
            print("'student.sqlite'数据文件已经存在")
            msgBox2 = QMessageBox()
            msgBox2.setText("'student.sqlite'数据文件已经存在")
            msgBox2.exec()

        db.setHostName("127.0.0.1")#可以有多个连接到同一个数据库,也就是说连接名不唯一
        db.setUserName('tom')#定义用户名
        db.setPassword('tom@123')

        # success!
        db.open()
        table_text, table_action = QtWidgets.QInputDialog.getText(self, '表名称', '请输入表名称', QtWidgets.QLineEdit.Normal)
        if (table_text.replace(' ', '') != '') and (table_action is True):
             print(table_text)
        #实例化一个查询对象
        self.tablename=table_text

        #先进行插入数据

        query = QtSql.QSqlQuery()
        if query.exec_("Drop table if exists s"):
            print("drop table s ok!")
        if query.exec_("CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20))"):
            print("create table s ok!")
        if query.exec_("Drop table if exists sc"):
            print("drop table sc ok!")
        if query.exec_("CREATE TABLE SC(sclass int,sno int,cno int ,grade int)"):
            print("create table sc ok!")
        if query.exec_("Drop table if exists c"):
            print("drop table c ok!")
        else:
            print("error:drop table c")
        if query.exec_("CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int)"):
            print("create table c ok!")
        else:
            print("error:create table c")

        query.exec_("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
        query.exec_("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
        query.exec_("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
        query.exec_("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
        query.exec_("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
        query.exec_("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")

        query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
        query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
        query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
        query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
        query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
        query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
        query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
        query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
        query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
        query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

        query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
        query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
        query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
        query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
        query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
        query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
        query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
        query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
        query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
        query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

        db.close()

    def showall_tab(self):
        query = QtSql.QSqlQuery()
        if (self.tablename == "s"):
            msgBox3 = QMessageBox()
            msgBox3.setText("展示表s")
            msgBox3.exec()

            self.model = QtSql.QSqlTableModel(
                self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            # model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
            self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
            self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

            self.model.setTable("s")
            self.model.select()
            self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

        elif (self.tablename == "sc"):
            msgBox4 = QMessageBox()
            msgBox4.setText("展示表sc")
            msgBox4.exec()

            self.model = QtSql.QSqlTableModel(
                self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            # model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')


            self.model.setTable("sc")
            self.model.select()
            self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

        elif (self.tablename == "c"):
            msgBox5 = QMessageBox()
            msgBox5.setText("展示表c")
            msgBox5.exec()

            self.model = QtSql.QSqlTableModel(self.table_view)
            # onfieldchange模型的任何更改都会返回到数据库
            self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '课程名')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '先修课')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '学分')


            self.model.setTable("c")
            self.model.select()
            self.table_view.setModel(self.model)

        else:
            msgBox6 = QMessageBox()
            msgBox6.setText("表暂且不属于实验范围,请更换!")
            msgBox6.exec_()

    def search_data(self):
        query = QtSql.QSqlQuery()
        # 创建一个数据库表
        if(self.tablename=="s"):
            msgBox3 = QMessageBox()
            msgBox3.setText("查询表s")
            msgBox3.exec()

            self.model = QtSql.QSqlTableModel(self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            #model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
            self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
            self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

            search = self.text.text()
            self.model.setTable("s")
            self.model.setFilter("sno={}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

        elif(self.tablename=="sc"):
            msgBox4 = QMessageBox()
            msgBox4.setText("查询表sc")
            msgBox4.exec()

            self.model = QtSql.QSqlTableModel(self.table_view) # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            #model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')

            search = self.text.text()
            self.model.setTable("sc")
            self.model.setFilter("sno = {}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

        elif(self.tablename=="c"):
            msgBox5 = QMessageBox()
            msgBox5.setText("查询表c")
            msgBox5.exec()

            self.model=QtSql.QSqlTableModel(self.table_view)
            #onfieldchange模型的任何更改都会返回到数据库
            self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
            self.model.setHeaderData(0,QtCore.Qt.Horizontal,'课程号')
            self.model.setHeaderData(1,QtCore.Qt.Horizontal,'课程名')
            self.model.setHeaderData(2,QtCore.Qt.Horizontal,'先修课')
            self.model.setHeaderData(3,QtCore.Qt.Horizontal,'学分')

            search=self.text.text()
            self.model.setTable("c")
            self.model.setFilter("cno = {}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)

        else:
            msgBox6=QMessageBox()
            msgBox6.setText("表暂且不属于实验范围,请更换!")
            msgBox6.exec_()

    def add_row_data(self):
        #不是直接操作QTableView,而是对model模型进行添加
        # 如果存在实例化的数据模型对象
        # self.model.insertRow(self.model.rowCount(),1)

        if self.model:
            #rowCount()得到行数,然后添加一行
            self.model.insertRows(self.model.rowCount(), 1)
            self.model.submitAll()#提交修改
        else:
            self.create_db()

    def del_row_data(self):
        if self.model:
            self.model.removeRow(self.table_view.currentIndex().row())
            self.model.submitAll()#提交修改
        else:
            self.create_db()

    def edit_row_data(self):
        if self.model:
            self.model.submitAll()#提交更改
        else:
            self.create_db()

    def backup_data(self):
        ori_file_name = r'D:\coding_programs\PythonPrograms\database_exp4\student.sqlite'  # 输入文件路径
        if os.path.isfile(ori_file_name):  # 判断该路径的是否是文件
            # 截取文件名,重组文件名
            seek_num = ori_file_name.rfind('.')
            new_file_name = ori_file_name[:seek_num] + '.bak'
            # 打开源文件
            old_file = open(ori_file_name, 'rb')
            # 读取文件信息
            old_file_content = old_file.read()
            # 创建新文件
            new_file = open(new_file_name, 'wb')
            # 将原始文件信息写入
            new_file.write(old_file_content)
            # 关闭文件
            old_file.close()
            new_file.close()
            print("backup success!")
            msgBox7 = QMessageBox()
            msgBox7.setText("student.bak数据文件已经备份")
            msgBox7.exec()
        else:
            print('没有该文件')

    def initUi(self):
        # 设置窗口标题
        self.setWindowTitle("刘看日的数据库实验四")
        # 设置窗口大小
        self.resize(600, 400)

        # 创建一个窗口部件
        self.widget = QtWidgets.QWidget()
        # 创建一个网格布局
        self.grid_layout = QtWidgets.QGridLayout()
        # 设置窗口部件的布局为网格布局
        self.widget.setLayout(self.grid_layout)

        # 创建一个工具组
        self.group_box = QtWidgets.QGroupBox('功能按钮')
        self.group_box_layout = QtWidgets.QVBoxLayout()
        self.group_box.setLayout(self.group_box_layout)


        #设置一个LineEdit窗口
        self.text=QtWidgets.QLineEdit()
        # 设置文本框的默认浮现文本
        self.text.setPlaceholderText("输入学号/课程号")

        self.table_view = QtWidgets.QTableView()
        # 按钮控件设置
        self.btn_create=QPushButton("连接表")
        self.btn_showall=QPushButton("展示全部数据")
        self.btn_search = QPushButton("基于学号/课程号查询")
        self.btn_close = QPushButton("退出")
        self.btn_delete=QPushButton("删除")
        self.btn_edit=QPushButton("修改")
        self.btn_add=QPushButton("添加")
        self.btn_backup = QPushButton("备份")

        # 添加按钮到group_box大组件中
        self.group_box_layout.addWidget(self.text)
        self.group_box_layout.addWidget(self.btn_create)
        self.group_box_layout.addWidget(self.btn_showall)
        self.group_box_layout.addWidget(self.btn_search)
        self.group_box_layout.addWidget(self.btn_add)
        self.group_box_layout.addWidget(self.btn_delete)
        self.group_box_layout.addWidget(self.btn_edit)
        self.group_box_layout.addWidget(self.btn_backup)
        self.group_box_layout.addWidget(self.btn_close)

        # 将上述两个部件添加到网格布局中
        self.grid_layout.addWidget(self.table_view, 0, 0)  # 放置表格位置在0
        self.grid_layout.addWidget(self.group_box, 0, 1)  # 放置
        # 创建按钮功能按钮
        self.btn_create.clicked.connect(self.create_db)
        self.btn_showall.clicked.connect(self.showall_tab)
        self.btn_search.clicked.connect(self.search_data)
        self.btn_close.clicked.connect(self.close)
        self.btn_add.clicked.connect(self.add_row_data)
        self.btn_delete.clicked.connect(self.del_row_data)
        self.btn_edit.clicked.connect(self.edit_row_data)
        self.btn_backup.clicked.connect(self.backup_data)
        # 设置UI界面的核心部件
        self.setCentralWidget(self.widget)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = MainUi()
    gui.show()
    sys.exit(app.exec_())
posted @ 2021-06-26 09:47  flybird2008  阅读(8)  评论(0)    收藏  举报  来源