十一、学生信息管理系统(PyQt5+MySQL+PyMySQL模块实现)

news/2024/5/19 13:37:38

      随着教育的普及,各学校学会人数越来越多,学生信息管理一直被视为校园管理中的一个瓶颈,传统的管理方式并不能适应时代发展。其中,学生信息管理主要包括学籍管理、科学管理、课外活动管理、学生成绩管理、生活管理等内容。
      本节使用Python+PyQt5+MySQL开发一个学生信息管理系统,主要对学生的基本信息及所在班级、年级信息进行管理。

1. 需求分析

  1. 简单友好的操作窗体,以方便管理员的日常管理工作;
  2. 整个系统的操作流程简单,易于操作;
  3. 完备的学生基本信息管理及班级年级管理功能;
  4. 全面的系统维护管理,方便系统日后维护工作;
  5. 强大的基础信息设置功能。

2. 系统设计

      主要包括系统功能结构、系统业务流程和系统预览等内容。

1. 系统功能结构

其中,基本信息管理和系统查询为本系统的核心功能。
在这里插入图片描述

2. 系统业务流程

在这里插入图片描述

3. 系统预览

      学生信息管理系统由多个窗体组成。

      系统登录窗体主要用于限制非法用户进入系统内部。
在这里插入图片描述

      系统主窗体的主要功能是调用执行本系统的所有功能。
在这里插入图片描述

      年级信息设置窗体的主要功能是对年级的信息进行增、删、改操作。
在这里插入图片描述

      班级信息设置窗体的主要功能是对班级信息进行增、删、改操作。
在这里插入图片描述

      学生信息管理窗体的主要功能是对学生基本信息进行添加、修改、删除操作。
在这里插入图片描述

      学生信息查询窗体的主要功能是查询学生的基本信息。
在这里插入图片描述

      用户信息维护窗体的主要功能是对系统的登录用户及对应密码进行添加、删除和修改操作。
在这里插入图片描述

3. 系统开发必备

1. 系统开发环境

  1. 操作系统:Windows 7、Windows 10等。
  2. Python版本:Python 3.9.0。
  3. 开发工具:PyCharm。
  4. 数据库:MySQL。
  5. Python内置模块:sys。
  6. 第三方模块:PyQt5、pyqt5-tools、PyMySQL。

2. 系统组织结构

在这里插入图片描述

4. 数据库设计

      学生信息管理系统主要用于管理学生的基本信息,因此除了基本的学生信息表之外,还要设计年级信息表、班级信息表等。

1. 数据库结构设计

      本系统采用MySQL作为数据库,MySQL数据库作为一个开源、免费的数据库系统,其以简单、易用、数据存取速度快等特点赢得了开发者的喜爱。学生信息管理系统的数据库名称为db_student,共包含4张数据表和两个视图。
在这里插入图片描述

2. 数据表结构设计

1. tb_class(班级信息表)

  • 主要用于保存班级信息。
字段名称数据类型长度是否是主键描述
classIDint班级编号
gradeIDint年级编号
classNamevarchar20班级名称

在这里插入图片描述

2. tb_grade表

  • 年级信息表,主要用来保存年级信息。
字段名称数据类型长度是否是主键描述
gradeIDint年级编号
gradeNamevarchar20年级名称

在这里插入图片描述

3. tb_student表

  • 用来保存学生信息。
字段名称数据类型长度是否是主键描述
stuIDvarchar20学生编号
stuNamevarchar20学生姓名
classIDint班级编号
gradeIDint年级编号
ageint年龄
sexint4性别
phonechar20联系电话
addressvarchar100家庭地址

在这里插入图片描述

4. tb_user表

  • 系统用户表,主要用来保存系统的登录用户相关信息。
字段名称数据类型长度是否是主键描述
userNamevarchar20用户姓名
userPwdvarchar50用户密码

在这里插入图片描述

3. 视图设计

      为了使数据查询更方便快捷,减少数据表连接查询带来的麻烦,我们将创建2个视图。

1. v_classinfo(班级及年级信息视图)

  • v_classinfo视图主要为了查询年级及对应班级的详细信息。
    创建的代码如下:
# 1. 创建v_classinfo视图
use db_student;
drop view if exists v_classinfo;
create view v_classinfo as 
select tb_class.classID as classID,
tb_grade.gradeID as gradeID,
tb_grade.gradeName as gradeName,
tb_class.className as className
from (tb_class join tb_grade)
where (tb_class.gradeID=tb_grade.gradeID);

在这里插入图片描述

2. v_studentifno(学生详细信息视图)

  • v_studentinfo视图主要为了查询学生的详细信息。
    创建的代码如下:
# 2. 创建v_studentinfo视图
use db_student;

drop view if exists v_studentinfo;

create view v_studentinfo as
select tb_student.stuID as stuID,
tb_student.stuName as stuName,
tb_student.age as age,
tb_student.sex as sex,
tb_student.phone as phone,
tb_student.address as address,
tb_class.className as className,
tb_grade.gradeName as gradeName
from ((tb_student join tb_class) join tb_grade)
where ((tb_student.classID = tb_class.classID) and (tb_student.gradeID = tb_grade.gradeID));

在这里插入图片描述

5. 公共模块设计

      开发Python项目时,将常用的代码封装为模块,可以大大提高代码重用率。本系统中创建一个service.py公共模块,主要用来连接数据库,并实现数据库的添加、修改、删除、模糊查询和精确查询等功能,在实现具体的窗体模块功能时,只需要调用service.py公共模块中的相应方法即可。

1. 模块导入及公共变量

      由于需要对MySQL数据库进行操作,所以在service.py中需要导入PyMySQL模块。

import pymysql   # 导入操作MySQL数据库的模块   # pip install PyMSQL

      定义一个全局变量userName,用来记录登录的用户名。

userName=""     # 记录用户名   # 全局变量

2. 打开数据库连接

      定义一个open()方法,用来使用PyMySQL模块中的connect()方法连接指定的MySQL数据库,并返回一个连接对象。

# 打开数据库连接
def open():
    db = pymysql.connect(host="locahost", user="root", password="123456", database="db_student", charset="utf8")
    return db      # 返回连接对象

3. 数据的增删改

      定义一个exec()方法,主要实现数据库的添加、修改和删除功能,该方法有2个参数,第一个参数是要执行的SQL语句;第二个参数是一个元组,表示SQL语句中要用到的参数。

# 执行数据库的增、删、改操作
def exec(sql, values):
    db = open()     # 连接数据库
    cursor = db.cursor()      # 使用cursor()方法获取操作游标
    try:
        cursor.execute(sql, values)    # 执行增删改的SQL语句
        db.commit()   # 提交数据
        return 1      # 执行成功
    except:
        db.rollback()      # 发生错误时回滚
        return 0
    finally:
        cursor.close()     # 关闭游标
        db.close()     # 关闭数据库连接

4. 数据的查询方法

      定义一个query()方法,用来实现带参数的精确查询,该方法中有两个参数,第一个参数为要执行的SQL查询语句;第二个参数为可变参数,表示SQL查询语句中需要用到的参数。

# 带参数的精确查询
def query(sql, *keys):
    db = open()     # 连接数据库
    cursor = db.cursor()       # 使用cursor()方法获取操作游标
    cursor.execute(sql, keys)       # 执行查询 SQL语句
    result = cursor.fetchall()     # 记录查询结果
    cursor.close()      # 关闭游标
    db.close()      # 关闭数据库连接
    return result    # 返回查询结果

      定义一个query2()方法,用来实现不带参数的模糊查询,该方法中只有一个参数,表示要执行的SQL查询语句。其中,SQL查询语句中可以使用like关键字和通配符进行模糊查询。

# 不带参数的模糊查询
def query2(sql):
    db = open()      # 连接数据库
    cursor = db.cursor()    # 使用cursor()方法获取操作游标
    cursor.execute(sql)      # 执行查询SQL语句
    result = cursor.fetchall()     # 记录查询结果
    cursor.close()     # 关闭游标
    db.close()     # 关闭数据库连接
    return result    # 返回查询结果

6. 登录模块设计

      使用的数据表:tb_user。

1. 登录模块概述

      登录模块主要对输入的用户名和密码进行验证,如果没有输入用户名和密码,或者输入错误,弹出提示框,否则,进入学生信息管理系统的主窗体。
在这里插入图片描述

2. 模块的导入

      登录模块是在login.py文件中实现的,在该文件中,首先导入公共模块。

import sys    # 导入sys模块
import main
from service import service

      由于service.py模块在service文件夹中,所以使用from…import…形式导入。

3. 登录功能的实现

      定义一个openMain()方法,调用service模块中的query()方法查询输入的用户名和密码在tb_user数据表中是否存在,如果存在,记录当前登录用户名,并显示主窗体;若不存在,则提示用户输入正确的用户名和密码。

    # 打开主窗体
    def openMain(self):
        service.userName=self.editName.text() # 全局变量,记录用户名
        self.userPwd=self.editPwd.text() # 记录用户密码
        if service.userName != "" and self.userPwd != "": # 判断用户名和密码不为空
            # 根据用户名和密码查询数据
            result=service.query("select * from tb_user where userName = %s and userPwd = %s",service.userName,self.userPwd)
            if len(result)>0: # 如果查询结果大于0,说明存在该用户,可以登录
                self.m = main.Ui_MainWindow()  # 创建主窗体对象
                self.m.show()  # 显示主窗体
                MainWindow.hide() # 隐藏当前的登录窗体
            else:
                self.editName.setText("") # 清空用户名文本
                self.editPwd.setText("") # 清空密码文本框
                QMessageBox.warning(None, '警告', '请输入正确的用户名和密码!', QMessageBox.Ok)
        else:
            QMessageBox.warning(None, '警告', '请输入用户名和密码!', QMessageBox.Ok)

      定义openMain()方法后,将其分别绑定到“密码”输入框的editingFinished信号和“登录”按钮的clicked信号,以便在输入密码后按Enter键,或者单击“登录”按钮时,能够执行登录操作。

     # 输入密码后按Enter键执行登录操作
     self.editPwd.editingFinished.connect(self.openMain)
     # 单击“登录”按钮执行登录操作
     self.btnLogin.clicked.connect(self.openMain)

4. 退出登录窗体

      单击“退出”按钮,关闭当前的登录窗口,该功能主要是通过为“退出”按钮的clicked信号绑定内置close()函数实现的。

     self.btnExit.clicked.connect(MainWindow.close)   # 关闭登录窗体

5. 在Python中启动登录窗体

      在login.py中加入主方法:


# 主方法
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
    ui = Ui_MainWindow() # 创建PyQt5设计的窗体对象
    ui.setupUi(MainWindow) # 调用PyQt5窗体的方法对窗体对象进行初始化设置
    MainWindow.show() # 显示窗体
    sys.exit(app.exec_()) # 程序关闭时退出进程

7. 主窗体模块设计

1. 主窗体概述

      主窗体是学生信息管理系统与用户交互的一个重要窗口,因此要求一定要设计合理,该主窗体主要包括一个菜单栏,通过该菜单栏中的菜单项,用户可以打开各个功能窗体,也可以退出本系统;另外,为了界面美观,本程序为主窗体设置了背景图片,并且背景图片自动适应主窗体的大小。
在这里插入图片描述

2. 模块导入及窗体初始化

      主窗体是在main.py中实现的,由于主窗体中需要打开各个功能窗体,因此需要导入项目中创建的窗体对应的模块,并且导入公共服务模块service。

     from PyQt5.QtWidgets import *
     from service import service
     from baseinfo import student
     from query import studentinfo
     from settings import classes,grade
     from system import user

      使用Qt Designer设计的窗体,在转换为.py文件时,默认继承object类,但为了能够在窗体间互相调用,需要将其继承类修改为QMainWindow,并且为它们添加__init__方法,在该方法中可以对窗体进行初始化,并且设置窗体的显示样式。

class Ui_MainWindow(QMainWindow):
    # 构造方法
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setWindowFlags(QtCore.Qt.MSWindowsFixedSizeDialogHint)  # 只显示最小化和关闭按钮
        self.setupUi(self) # 初始化窗体设置

      其他功能窗体都需要按照上面代码修改继承类,并添加__init__()方法。

3. 在主窗体中打开其他功能窗体

      在学生信息管理系统的主窗体中,选择相应菜单下的菜单项,可以打开相应的功能窗体。
在这里插入图片描述

    # 基础设置菜单对应槽函数
    def openSet(self,m):
        if m.text()=="年级设置":
            self.m = grade.Ui_MainWindow()  # 创建年级设置窗体对象
            self.m.show()  # 显示窗体
        elif  m.text()=="班级设置":
            self.m = classes.Ui_MainWindow()  # 创建班级设置窗体对象
            self.m.show()  # 显示窗体

      为“基础设置”菜单的triggered信号关联自定义的openSet()方法。

     # 为基础设置菜单中的QAction绑定triggered信号
     self.menu.triggered[QtWidgets.QAction].connect(self.openSet)

4. 显示当前登录用户和登录时间

      在主窗体的状态栏中可以显示当前的登录用户、登录时间和版权信息,其中,当前登录用户可以通过公共模块service中的全局变量userName获取,而登录时间可以使用PyQt5中的QDateTime类的currentDateTime()方法获取。

8. 年级设置模块设计

      使用数据表:tb_grade、tb_class

1. 年级设置模块概述

      年级设置模块用来维护年级的基本信息,包括对年级信息的添加、修改和删除等操作。在系统主窗体的菜单栏中选择“基本设置”→“年级设置”菜单,可以进入年级设置模块。
在这里插入图片描述
      班级设置模块和用户信息维护模块的实现原理与年级设置模块类似。

2. 模块导入

      年级设置模块在grade.py文件中实现,在该文件中,首先导入公共模块。

     from PyQt5.QtWidgets import *
     import sys
     sys.path.append("../")     # 设置模块的搜索路径
     from service import service

      在导入service公共模块之前,使用了代码sys.path.append(“…/”),该代码的作用是将当前路径的上一级添加到模块搜索路径中。service.py模块文件在service文件夹中,而grade.py文件在settings文件夹中,两者不在同一级目录下,所以,如果直接添加service模块,会出现找不到模块的情况,而使用sys.path.append(“…/”)后,相当于将搜索路径定位到当前路径的上一级,而上一级有service文件夹,因此就可以使用“from…import…”的形式导入service文件夹下的公共模块了。

3. 窗体加载时显示所有年级信息

      级设置模块运行时,首先将数据库中存储的所有年级信息显示在表格中,这主要是通过自定义方法query()实现的。在该方法中,调用service公共模块中的query()方法从tb_grade数据表中获取所有数据,并显示在表格中。

    # 查询年级信息,并显示在表格中
    def query(self):
        self.tbGrade.setRowCount(0)  # 清空表格中的所有行
        result = service.query("select * from tb_grade")  # 调用服务类中的公共方法执行查询语句
        row = len(result)  # 取得记录个数,用于设置表格的行数
        self.tbGrade.setRowCount(row)  # 设置表格行数
        self.tbGrade.setColumnCount(2)  # 设置表格列数
        # 设置表格的标题名称
        self.tbGrade.setHorizontalHeaderLabels(['年级编号', '年级名称'])
        for i in range(row):  # 遍历行
            for j in range(self.tbGrade.columnCount()):  # 遍历列
                data = QTableWidgetItem(str(result[i][j]))  # 转换后可插入表格
                self.tbGrade.setItem(i, j, data)  # 设置每个单元格的数据

4. 年级信息的添加

      在添加年级信息时,首先需要判断要添加的年级是否存在,这里定义一个getName()方法,根据年级名称在tb_grade数据表中查询数据,并返回结果集中的数量,如果该数量大于0,说明已经存在相应年级;否则,说明数据表中没有要添加的年级,这时用户即可正常进行添加操作。

     def getName(self,name):
     result = service.query("select * from tb_grade where gradeName = %s", name)
     return len(result)

      自定义一个add()方法,用来实现添加年级信息的功能,在该方法中,首先需要调用上面自定义的getName()方法判断是否可以正常添加,如果可以,则调用service公共模块中的exec()方法执行添加年级信息的SQL语句,并刷新表格,以显示最新添加的年级。

    # 添加年级信息
    def add(self):
        gradeID = self.editID.text()  # 记录输入的年级编号
        gradeName = self.editName.text()  # 记录输入的年级名称
        if gradeID != "" and gradeName != "":  # 判断年级编号和年级名称不为空
            if self.getName(gradeName)>0:
                self.editName.setText("")
                QMessageBox.information(None, '提示', '您要添加的年级已经存在,请重新输入!', QMessageBox.Ok)
            else:
                # 执行添加语句
                result = service.exec("insert into tb_grade(gradeID,gradeName) values (%s,%s)", (gradeID, gradeName))
                if result > 0:  # 如果结果大于0,说明添加成功
                    self.query()  # 在表格中显示最新数据
                    QMessageBox.information(None, '提示', '信息添加成功!', QMessageBox.Ok)
        else:
            QMessageBox.warning(None, '警告', '请输入数据后,再执行相关操作!', QMessageBox.Ok)

      将自定义的add()方法与“添加”按钮的clicked信号关联,以便在单击“添加”按钮时,调用add()方法添加年级信息。

     self.btnAdd.clicked.connect(self.add)    # 绑定添加按钮的单击信号

5. 年级信息的修改

      在修改年级信息时,首先需要确定要修改的年级,因此,定义一个getItem()方法,用来获取表格中选中的年级编号。

    # 获取选中的表格内容
    def getItem(self, item):
        if item.column() == 0:  # 如果单击的是第一列
            self.select = item.text()  # 获取单击的单元格文本
            self.editID.setText(self.select)  # 显示在文本框中

      将定义的getItem()方法与表格的项单击信号itemClicked关联。

     self.tbGrade.itemClicked.connect(self.getItem)     # 获取选中的单元格数据

      定义一个edit()方法,首先判断是否选择了要修改的年级,如果没有,弹出信息提示,否则,调用service公共模块中的exec()方法执行修改年级信息的SQL语句,并刷新表格,以显示修改指定年级后的最新数据。

    # 修改年级信息
    def edit(self):
        try:
            if self.select != "":  # 判断是否选择了要修改的数据
                gradeName = self.editName.text()  # 记录修改的年级名称
                if gradeName != "":  # 判断年级名称不为空
                    if self.getName(gradeName) > 0:
                        self.editName.setText("")
                        QMessageBox.information(None, '提示', '您要修改的年级已经存在,请重新输入!', QMessageBox.Ok)
                    else:
                        # 执行修改操作
                        result = service.exec("update tb_grade set gradeName= %s where gradeID=%s", (gradeName, self.select))
                        if result > 0:  # 如果结果大于0,说明修改成功
                            self.query()  # 在表格中显示最新数据
                            QMessageBox.information(None, '提示', '信息修改成功!', QMessageBox.Ok)
        except:
            QMessageBox.warning(None, '警告', '请先选择要修改的数据!', QMessageBox.Ok)

      将自定义的edit()方法与“修改”按钮的clicked信号关联,以便在单击“修改”按钮时,调用edit()方法修改年级信息。

     self.btnEdit.clicked.connect(self.edit)    # 绑定修改按钮的单击信号

6. 年级信息的删除

      定义一个delete()方法,首先判断是否选择了要删除的年级,如果没有,弹出信息提示,否则,调用service公共模块中的exec()方法执行删除年级信息的SQL语句,并删除该年级所包含的所有班级,最后刷新表格,以显示删除指定年级后的最新数据。

    # 删除年级信息
    def delete(self):
        try:
            if self.select != "":  # 判断是否选择了要删除的数据
                # 执行删除年级操作
                result = service.exec("delete from tb_grade where gradeID= %s", (self.select,))
                if result > 0:  # 如果结果大于0,说明删除成功
                    self.query()  # 在表格中显示最新数据
                # 删除年级下的所有班级
                result = service.exec("delete from tb_class where gradeID= %s", (self.select,))
                if result > 0:  # 如果结果大于0,说明删除成功
                    self.query()  # 在表格中显示最新数据
                QMessageBox.information(None, '提示', '信息删除成功!', QMessageBox.Ok)
        except:
            QMessageBox.warning(None, '警告', '请先选择要删除的数据!', QMessageBox.Ok)

      将自定义的delete()方法与“删除”按钮的clicked信号关联,以便在单击“删除”按钮时,调用delete()方法删除年级信息。

     self.btnDel.clicked.connect(self.delete)   # 绑定删除按钮的单击信号

9. 学生信息管理模块设计

      使用的数据表:tb_student、tb_grade、tb_class、v_classinfo、v_studentinfo。

1. 学生信息管理模块概述

      学生信息管理模块用来管理学生的基本信息,包括学生信息的添加、修改、删除、基本查询等功能。在系统主窗体的菜单栏中选择“基本信息管理/学生管理”菜单,可以进入该模块。
在这里插入图片描述

2. 根据年级显示对应班级

      自定义一个bindGrade()方法,主要使用service公共模块中的query()方法从tb_grade表中获取所有年级的名称,并显示在“所属年级”下拉列表中。

    # 获取所有年级,显示在下拉列表中
    def bindGrade(self):
        self.cboxGrade.addItem("所有")
        result = service.query("select gradeName from tb_grade")  # 从年级表中查询数据
        for i in result:  # 遍历查询结果
            self.cboxGrade.addItem(i[0])  # 在下拉列表中显示年级

      自定义一个bindClass()方法,主要使用service公共模块中的query()方法从v_classinfo视图中获取指定年级所包含的所有班级的名称,并显示在“所属班级”下拉列表中。

    # 根据年级获取相应班级,显示在下拉列表中
    def bindClass(self):
        self.cboxClass.clear()  # 清空列表
        self.cboxClass.addItem("所有")  # 增加首选项
        result = service.query("select className from v_classinfo where gradeName=%s",
                               self.cboxGrade.currentText())  # 从年级视图中查询数据
        for i in result:  # 遍历查询结果
            self.cboxClass.addItem(i[0])  # 在下拉列表中显示班级

      将自定义的bindClass()方法绑定到“所属年级”下拉列表的currentIndexChanged信号,以便在选择年级时,执行bindClass()方法。

     self.cboxGrade.currentIndexChanged.connect(self.bindClass)   # 根据年级绑定班级列表

3. 学生信息查询

      加载学生信息管理模块时,会显示所有的学生信息,而在选择了年级和班级后,单击“刷新”按钮,可以显示指定年级下的指定班级的所有学生信息,该功能主要是通过自定义的query()方法实现的。在该方法中,主要调用service公共模块中的query()方法执行相应的SQL查询语句,并将查询到的学生信息显示在表格中。

    # 查询学生信息,并显示在表格中
    def query(self):
        self.tbStudent.setRowCount(0)  # 清空表格中的所有行
        gname = self.cboxGrade.currentText()  # 记录选择的年级
        cname = self.cboxClass.currentText()  # 记录选择的班级
        # 获取所有学生信息
        if gname == "所有":
            result = service.query("select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo")
        # 获取指定年级学生信息
        elif gname != "所有" and cname == "所有":
            result = service.query(
                "select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo where gradeName=%s", gname)
        # 获取指定年级指定班的学生信息
        elif gname != "所有" and cname != "所有":
            result = service.query(
                "select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo where gradeName=%s and className=%s",
                gname, cname)
        row = len(result)  # 取得记录个数,用于设置表格的行数
        self.tbStudent.setRowCount(row)  # 设置表格行数
        self.tbStudent.setColumnCount(7)  # 设置表格列数
        # 设置表格的标题名称
        self.tbStudent.setHorizontalHeaderLabels(['学生编号', '学生姓名', '班级', '性别', '年龄', '家庭地址', '联系电话'])
        for i in range(row):  # 遍历行
            for j in range(self.tbStudent.columnCount()):  # 遍历列
                data = QTableWidgetItem(str(result[i][j]))  # 转换后可插入表格
                self.tbStudent.setItem(i, j, data)  # 设置每个单元格的数据

4. 添加学生信息

      单击“添加”按钮,可以将用户选择和输入的信息添加到学生信息表中,该功能主要是通过自定义的add()方法实现的。add()方法实现的关键是,获取所选年级和班级的ID,然后执行insert into添加语句,向tb_student数据表中添加新数据。

    # 添加学生信息
    def add(self):
        stuID = self.editID.text()  # 记录学生编号
        stuName = self.editName.text()  # 记录学生姓名
        age = self.editAge.text()  # 记录年龄
        sex = self.cboxSex.currentText()  # 记录性别
        phone = self.editPhone.text()  # 记录电话
        address = self.editAddress.text()  # 记录地址
        if self.cboxGrade.currentText() != "" and self.cboxGrade.currentText() != "所有":  # 如果选择了年级
            # 获取年级对应的ID
            result = service.query("select gradeID from tb_grade where gradeName=%s", self.cboxGrade.currentText())
            if len(result) > 0:  # 如果结果大于0
                gradeID = result[0]  # 记录选择的年级对应的ID
                if self.cboxClass.currentText() != "" and self.cboxClass.currentText() != "所有":  # 如果选择了班级
                    # 获取班级对应的ID
                    result = service.query("select classID from tb_class where gradeID=%s and className=%s", gradeID,
                                           self.cboxClass.currentText())
                    if len(result) > 0:  # 如果结果大于0
                        classID = result[0]  # 记录选择的班级对应的ID
                        if stuID != "" and stuName != "":  # 判学生编号和学生姓名不为空
                            if self.getName(stuID) > 0:  # 判断已经存在该记录
                                self.editID.setText("")  # 清空学生编号文本框
                                QMessageBox.information(None, '提示', '您要添加的学生编号已经存在,请重新输入!', QMessageBox.Ok)
                            else:
                                # 执行添加语句
                                result = service.exec(
                                        "insert into tb_student(stuID,stuName,classID,gradeID,age,sex,phone,address) values (%s,%s,%s,%s,%s,%s,%s,%s)",
                                        (stuID, stuName, classID, gradeID, age, sex, phone, address))
                                if result > 0:  # 如果结果大于0,说明添加成功
                                    self.query()  # 在表格中显示最新数据
                                    QMessageBox.information(None, '提示', '信息添加成功!', QMessageBox.Ok)
                else:
                    QMessageBox.warning(None, '警告', '请输入数据后,再执行相关操作!', QMessageBox.Ok)
        else:
            QMessageBox.warning(None, '警告', '请先添加年级!', QMessageBox.Ok)

5. 根据选中编号显示学生详细信息

      当用户在显示学生信息的表格中单击某学生编号时,可以通过单击的编号获取该学生的详细信息,并显示到相应的文本框和下拉列表中,该功能是通过自定义的getItem()方法实现的。

    # 获取选中的表格内容
    def getItem(self, item):
        if item.column() == 0:  # 如果单击的是第一列
            self.select = item.text()  # 获取单击的单元格文本
            self.editID.setText(self.select)  # 显示在学生编号文本框中
            # 根据学生编号查询学生信息
            result = service.query("select * from v_studentinfo where stuID=%s",item.text())
            self.editName.setText(result[0][1]) # 显示学生姓名
            self.editAge.setText(str(result[0][2])) # 显示年龄
            self.editPhone.setText(result[0][4]) # 显示电话
            self.editAddress.setText(result[0][5]) # 显示地址
            self.cboxSex.setCurrentText(result[0][3]) # 显示性别

      将定义的getItem()方法与表格的项单击信号itemClicked关联。

     self.tbStudent.itemClicked.connect(self.getItem)   # 获取选中的单元格数据

6. 修改学生信息

      单击“修改”按钮,可以修改指定学生的信息,该功能主要是通过自定义的edit()方法实现的。在edit()方法中,首先需要判断是否选择了要修改的学生编号,如果没有,弹出信息提示;否则,执行update修改语句,修改tb_student数据表中的指定记录,并且刷新表格,以显示修改指定学生信息后的最新数据。

    # 修改学生信息
    def edit(self):
        try:
            if self.select != "":  # 判断是否选择了要修改的数据
                stuID = self.select  # 记录要修改的学生编号
                age = self.editAge.text()  # 记录年龄
                sex = self.cboxSex.currentText()  # 记录性别
                phone = self.editPhone.text()  # 记录电话
                address = self.editAddress.text()  # 记录地址
                # 执行修改操作
                result = service.exec("update tb_student set age=%s ,sex= %s,phone= %s,address= %s where stuID=%s",
                                      (age, sex, phone, address, stuID))
                if result > 0:  # 如果结果大于0,说明修改成功
                    self.query()  # 在表格中显示最新数据
                    QMessageBox.information(None, '提示', '信息修改成功!', QMessageBox.Ok)
        except:
            QMessageBox.warning(None, '警告', '请先选择要修改的数据!', QMessageBox.Ok)

7. 删除学生信息

      单击“删除”按钮,可以删除指定学生的信息,该功能主要是通过自定义的delete()方法实现的。在delete()方法中,首先需要判断是否选择了要删除的学生编号,如果没有,弹出信息提示;否则,执行delete删除语句,删除tb_student数据表中的指定记录,并且刷新表格,以显示删除指定学生信息后的最新数据。

    # 删除学生信息
    def delete(self):
        try:
            if self.select != "":  # 判断是否选择了要删除的数据
                # 执行删除操作
                result = service.exec("delete from tb_student where stuID= %s", (self.select,))
                if result > 0:  # 如果结果大于0,说明删除成功
                    self.query()  # 在表格中显示最新数据
                    QMessageBox.information(None, '提示', '信息删除成功!', QMessageBox.Ok)
        except:
            QMessageBox.warning(None, '警告', '请先选择要删除的数据!', QMessageBox.Ok)

10. 学生信息表查询模块设计

      使用的数据表:v_studentinfo。

1. 学生信息查询模块概述

      学生信息查询模块用来根据学生编号或者学生姓名查询学生的相关信息。在系统主窗体的菜单栏中选择“系统查询”→学生信息查询”菜单,可以进入该模块。
在这里插入图片描述

2. 学生信息查询功能的实现

      学生信息的查询功能主要是通过自定义的query()方法实现的,在查询学生信息时,有以下3种情况。

  1. 查询所有学生信息:调用公共模块service中的query()方法精确查询;
  2. 根据学生编号查询学生信息:调用公共模块service中的query2()方法模糊查询;
  3. 根据学生姓名查询学生信息:调用公共模块service中的query2()方法模糊查询。
    # 查询学生信息,并显示在表格中
    def query(self):
        self.tbStudent.setRowCount(0)  # 清空表格中的所有行
        # 获取所有学生信息
        if self.editKey.text() == "":
            result = service.query(
                "select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo")
        else:
            key = self.editKey.text()  # 记录查询关键字
            # 根据学生编号查询信息
            if self.cboxCondition.currentText() == "学生编号":
                sql="select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo where stuID like '%" + key + "%'"
                result = service.query2(sql)
            # 根据学生姓名查询信息
            elif self.cboxCondition.currentText() == "学生姓名":
                sql = "select stuID,stuName,CONCAT(gradeName,className),sex,age,address,phone from v_studentinfo where stuName like '%" + key + "%'"
                result = service.query2(sql)
        row = len(result)  # 取得记录个数,用于设置表格的行数
        self.tbStudent.setRowCount(row)  # 设置表格行数
        self.tbStudent.setColumnCount(7)  # 设置表格列数
        # 设置表格的标题名称
        self.tbStudent.setHorizontalHeaderLabels(['学生编号', '学生姓名', '班级', '性别', '年龄', '家庭地址', '联系电话'])
        for i in range(row):  # 遍历行
            for j in range(self.tbStudent.columnCount()):  # 遍历列
                data = QTableWidgetItem(str(result[i][j]))  # 转换后可插入表格
                self.tbStudent.setItem(i, j, data)  # 设置每个单元格的数据

      本节按一个完整项目的开发过程讲解学生信息系统的实现:从前期的需求分析、系统设计,到数据库设计及公共模块设计,再到最终各个功能模块设计。
      学习本节我们能熟悉学生信息管理的流程,并熟练掌握使用Python结合MySQL数据库进行项目开发的相关技术。
完整的项目代码:https://download.csdn.net/download/ungoing/86764820


http://lihuaxi.xjx100.cn/news/83430.html

相关文章

y164.第九章 GitOps从入门到精通 -- ArgoCD快速入门和ArgoCD进阶(十三)

11.9 同步选项 同步选项(Sync Options)用于禁用或启用同步过程中的某些特性 ApplyOutOfSyncOnly 仅对那些处于OutOfSync状态的资源执行同步操作PrunePropagationPolicy 资源修剪传播策略,默认使用foreground策略 另外可选的策略还有background和orphan PruneLast 在同步操作…

java毕业设计房产交易系统Mybatis+系统+数据库+调试部署

java毕业设计房产交易系统Mybatis系统数据库调试部署 java毕业设计房产交易系统Mybatis系统数据库调试部署本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件:idea eclipse 前端技术:Layui、HTML、CSS、…

【pytorch】ValueError: Expected more than 1 value per channel when training

ValueError: Expected more than 1 value per channel when training一、解决方案二、问题分析三、深入分析,修改源码一、解决方案 dataloader设置参数 drop_lastTrue1 丢弃掉最后单独的样本在训练前用num_of_samples % batch_size 算一下会不会正好剩下一个样本2如…

【vuex】

文章目录资料安装使用快速开始基本使用(非模块化):例子:辅助函数导入参数mapStatemapGettersmapMutationsmapActions模块化:步骤:资料 尚硅谷视频:https://www.bilibili.com/video/BV1Zy4y1K7S…

武汉星起航:亚马逊产品被跟卖的应对方法

在亚马逊平台,是允许有跟卖的形式存在,当你的产品被一两个卖家跟卖,说明你的产品卖得好,但是如果你的产品被大量跟卖,那就要及时阻止,不然就要给别人作嫁衣了。 什么是跟卖? 几家欢喜几家愁&a…

2020ICPC南京【个人题解EFHKLM】

目录E - Evil Coordinate(思维、暴力)思路代码F - Fireworks(概率期望、三分)思路代码H - Harmonious Rectangle(思维、暴力)思路代码K - K Co-prime Permutation(签到、构造)思路代…

oracle 12c使用 SEED创建一个PDB

1 登录cdb export ORACLE_SIDorclcdb sqlplus / as sysdba 2 建pdb #这里利用pdbseed建一个orclpdb5 CREATE PLUGGABLE DATABASE orclpdb5 ADMIN USER pdbadmin IDENTIFIED BY oracle file_name_convert(pdbseed,orclpdb5) --看到会自动创建orclpdb5目录(和pdbseed并列)&…