学生信息管理系统
本案例由3个页面组成:
- 登录页面
- 注册页面
- 数据操作页面
用户若想使用我们这个系统,必须先注册,注册成功之后自动打开登录页面,登录成功即进入数据操作页面
案例展示
数据库创建
当前我们是要来开发一个新的项目,为了不和其它数据库糅杂在一下,我们就来新建一个数据库吧!
创建完数据库还不行啊,我们最好还能让管理员给我们一个账号,该账号只能在itheima这个数据库中使用,所以我们需要使用root
账号登陆
例如,我们创建一个系统管理员账号:admin
密码:123456
| create user admin@'localhost' identified by '123456'
|
创建完用户,我们还不要忘记对该用户授予itheima
这个数据库下所有的权限喔!
| grant all privileges on itheima.* to admin@'localhost';
|
至此,我们为这个新项目所做的数据库准备工作就完成啦!
表的创建
我们去创建一张专门用于存放系统使用人员的表,让它和我们系统要记录的学生信息表分开
例如,我们创建一张users
的表专门用于存放管理员门的表
| create table if not exists user(
id int primary key auto_increment,
username varchar(20),
password varchar(50),
nickname varchar(20)
);
|
创建一张专门用于保存学生信息的表student
| create table if not exists student(
sid int primary key auto_increment,
name varchar(20),
age int,
gender varchar(2)
)
|
搭建主窗体
主窗体拥有一个菜单栏,它里面有个操作选项,我们可以进行菜单切换,所以这里我们需要操作菜单栏
1
2
3
4
5
6
7
8
9
10
11
12 | # 添加操作菜单
menu_bar = self.window.menuBar()
operate_menu =menu_bar.addMenu("操作")
# 向菜单中添加两个动作
loginAction = QAction("登录")
loginAction.triggered.connect(self.show_login)
operate_menu.addAction(loginAction)
registerAction = QAction("注册")
registerAction.triggered.connect(self.show_register)
operate_menu.addAction(registerAction)
|
要想实现窗体的切换,我们还需要使用QT中的自定义信号
| from PyQt5.QtCore import pyqtSignal
class LoginWidget(QWidget):
# 声明一个信号
login_success = pyqtSignal()
....
# 向外发送一个信号
self.login_success.emit()
|
完整的主窗体实现代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 | from pymysql import connect
from PyQt5.QtWidgets import QApplication,QMainWindow,QAction
from RegisterWidget import RegisterWidget
from LoginWidget import LoginWidget
from IndexWidget import IndexWidget
import sys
class StuSystem:
def __init__(self):
# 初始化数据库
# self.create_db()
# 创建一个应用程序
app = QApplication(sys.argv)
# 创建一个主窗体
self.mainWindow = QMainWindow()
# 设置窗口的固定大小
self.mainWindow.setFixedSize(800,400)
# 给窗口增加一个菜单栏
menuBar = self.mainWindow.menuBar()
operation = menuBar.addMenu("操作")
# 给菜单添加动作
loginAction = QAction("登录")
# 将loginAction添加到操作这个菜单里
operation.addAction(loginAction)
# 设置loginAction的信号和槽
loginAction.triggered.connect(self.show_login)
# 给菜单添加注册的动作
registerAction = QAction("注册")
# 将registerAction添加到这个菜单中
operation.addAction(registerAction)
# 设置RegisterAction的信号和槽
registerAction.triggered.connect(self.show_register)
# 默认打开注册页面
self.show_index()
# 将主窗口显示出来
self.mainWindow.show()
# 让程序一直处于运行的状态
sys.exit(app.exec())
def show_index(self):
print("显示主要功能页")
indexWidget = IndexWidget()
self.mainWindow.setCentralWidget(indexWidget)
def show_login(self):
print("显示登录页面")
loginWidget = LoginWidget()
loginWidget.login_success.connect(self.show_index)
self.mainWindow.setCentralWidget(loginWidget)
def show_register(self):
print("显示注册页面")
registerWidget = RegisterWidget()
# 绑定信号和槽
registerWidget.register_success.connect(self.show_login)
self.mainWindow.setCentralWidget(registerWidget)
def create_db(self):
# 建立连接
conn = connect(host="localhost",port=3306,user="admin",password="123456")
# 获取执行SQL的游标
cursor = conn.cursor()
# 创建数据库
sql = "create database if not exists itheima"
# 执行sql
cursor.execute(sql)
# 选中数据库
cursor.execute("use itheima")
# 创建管理员账号表
sql = """create table if not exists user(
id int primary key auto_increment,
username varchar(20),
password varchar(50),
nickname varchar(20)
);"""
# 创建表
cursor.execute(sql)
# 创建用于保存学生数据的表
sql = """create table if not exists student(
sid int primary key auto_increment,
name varchar(20),
age int,
gender varchar(2)
)"""
cursor.execute(sql)
# 释放资源
cursor.close()
# 断开连接
conn.close()
if __name__ == '__main__':
StuSystem()
|
编写注册页面
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | from PyQt5.QtWidgets import *
from PyQt5.Qt import QFont
from PyQt5.QtCore import pyqtSignal
class RegisterWidget(QWidget):
# 定义一个注册成功的信号
register_success = pyqtSignal()
def __init__(self):
super(RegisterWidget, self).__init__()
# 整个注册页面是水平布局
hbox = QHBoxLayout(self)
hbox.addStretch()
# 添加要显示的内容
vbox = QVBoxLayout()
label = QLabel("学生管理系统")
font = QFont("微软雅黑",30)
font.setBold(True)
label.setFont(font)
vbox.addWidget(label)
hbox.addLayout(vbox)
# 添加注册信息框
formLayout = QFormLayout()
self.usernameEdit = QLineEdit()
formLayout.addRow("用户名:",self.usernameEdit)
self.passwordEdit = QLineEdit()
self.passwordEdit.setEchoMode(QLineEdit.Password)
formLayout.addRow("密码:", self.passwordEdit)
self.nicknameEdit = QLineEdit()
formLayout.addRow("昵称:", self.nicknameEdit)
pushButton = QPushButton("注册")
pushButton.clicked.connect(self.register)
formLayout.addRow("",pushButton)
vbox.addLayout(formLayout)
hbox.addStretch()
def register(self):
# print("假装注册逻辑已经完成啦!")
# 获取用户输入的内容
username = self.usernameEdit.text()
password = self.passwordEdit.text()
nickname = self.nicknameEdit.text()
from pymysql import connect
conn = connect(host="localhost",port=3306,user="admin",password="123456",database="itheima")
sql = "insert into user values(null,%s,%s,%s)"
cursor = conn.cursor()
ret = cursor.execute(sql,[username,password,nickname])
# 需要提交事务
conn.commit()
if ret==1:
print("注册成功!")
QMessageBox.information(None, '提示', '恭喜您,注册成功!')
# 发送信号
self.register_success.emit();
# 释放资源
cursor.close()
# 断开连接
conn.close()
|
编写登录页面
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 | from PyQt5.QtWidgets import *
from PyQt5.Qt import QFont
from PyQt5.QtCore import pyqtSignal
class LoginWidget(QWidget):
# 定义一个注册成功的信号
login_success = pyqtSignal()
def __init__(self):
super(LoginWidget, self).__init__()
# 整个注册页面是水平布局
hbox = QHBoxLayout(self)
hbox.addStretch()
# 添加要显示的内容
vbox = QVBoxLayout()
label = QLabel("学生管理系统")
font = QFont("微软雅黑",30)
font.setBold(True)
label.setFont(font)
vbox.addWidget(label)
hbox.addLayout(vbox)
# 添加注册信息框
formLayout = QFormLayout()
self.usernameEdit = QLineEdit()
formLayout.addRow("用户名:",self.usernameEdit)
self.passwordEdit = QLineEdit()
self.passwordEdit.setEchoMode(QLineEdit.Password)
formLayout.addRow("密码:", self.passwordEdit)
pushButton = QPushButton("登录")
pushButton.clicked.connect(self.login)
formLayout.addRow("",pushButton)
vbox.addLayout(formLayout)
hbox.addStretch()
def login(self):
# 获取用户输入的内容
username = self.usernameEdit.text()
password = self.passwordEdit.text()
from pymysql import connect
conn = connect(host="localhost", port=3306, user="admin", password="123456", database="itheima")
sql = "select * from user where username=%s and password=%s"
cursor = conn.cursor()
cursor.execute(sql, [username, password])
user = cursor.fetchone();
if user:
print("登录成功!")
# 发送信号
self.login_success.emit();
else:
QMessageBox.information(None,"提示","用户名或密码错误!")
# 释放资源
cursor.close()
# 断开连接
conn.close()
|
补充:在这个案例中,我们的所有密码都是明文存储的,为了安全起见,我们其实可以将我们的密码加密之后再保存到数据库中
这里我们可以使用md5这种加密方式,例如
| str = "123456"
m = hashlib.md5(str.encode("utf-8")).hexdigest()
|
如果你觉得采用这种方式还是不安全的话,我们还可以对我们的md5加密算法进行加盐操作,让用户输入的值拼接上一个特殊的字符串
| str = "123456"+"&%%*(%)"
m = hashlib.md5(str.encode("utf-8")).hexdigest()
|
编写项目主页
在这一小节中,我们将给大家介绍qt中是如何去操作数据库的!
首先我们要给大家介绍的是QT中如何进行数据库的连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | # 创建一个QT数据库客户端,这里的参数不能瞎填, https://doc.qt.io/qt-5/qsqldatabase.html#addDatabase
db = QSqlDatabase.addDatabase("QMYSQL")
# 设置host
db.setHostName("localhost")
# 设置端口号
db.setPort(3306)
# 设置连接用户名
db.setUserName("admin")
# 设置连接的密码
db.setPassword("123456")
# 设置连接的数据库名称
db.setDatabaseName("itheima")
# 打开数据库
db.open()
|
如果想使用QT直接执行SQL命令的话,我们需要用到QSQLQuery
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 | # 传入上面创建好的数据库客户端即可
query = QSqlQuery(db)
# 执行建表语句
query.exec("""
create table if not exists student(
sid int primary key,
name varchar(20),
age int,
sex varchar(2)
);
""")
def test_query(db):
query = QSqlQuery(db)
ret = query.exec("select * from student")
print(ret)
while query.next():
print(query.value(0))
print(query.value(1))
print(query.value(2))
print(query.value(3))
print("====================")
def test_insert(db):
query = QSqlQuery(db);
ret = query.exec("insert into student values(%d,'%s',%d,'%s')"%(2001,"老王",36,"男"))
print(query.lastError().text())
print(ret)
def test_update(db):
query = QSqlQuery(db);
ret = query.exec("update student set name='%s' where name='%s'"%("小王","老王"))
print(query.lastError().text())
print(ret)
def test_delete(db):
query = QSqlQuery(db);
ret = query.exec("delete from student where sid=%d"%2001)
print(query.lastError().text())
print(ret)
|
注意:
qt库中默认缺少mysql的驱动,
若python是32位的,则需要提供32位的libmysql.dll文件
若python是64位的,则需要提供64位的libmysql.dll文件
并将它复制到python安装目录\Lib\site-packages\PyQt5\Qt\bin
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 | from PyQt5.QtWidgets import *
from PyQt5.QtSql import QSqlTableModel,QSqlDatabase
from PyQt5.QtCore import Qt
class IndexWidget(QWidget):
def __init__(self):
super(IndexWidget, self).__init__()
hbox = QHBoxLayout(self)
# 左侧按钮组
groupBox = QGroupBox("数据库操作")
hbox.addWidget(groupBox)
# 设置groupBox布局方式
vbox = QVBoxLayout()
groupBox.setLayout(vbox)
# 查看
query_btn = QPushButton("查看数据")
query_btn.clicked.connect(self.query_db)
vbox.addWidget(query_btn)
# 增加
add_btn = QPushButton("增加一行")
add_btn.clicked.connect(self.add)
vbox.addWidget(add_btn)
# 删除
delete_btn = QPushButton("删除一行")
delete_btn.clicked.connect(self.delete)
vbox.addWidget(delete_btn)
# 退出
exit_btn = QPushButton("退出")
exit_btn.clicked.connect(QApplication.exit)
vbox.addWidget(exit_btn)
# 右侧表格显示区域
self.tableView = QTableView()
hbox.addWidget(self.tableView)
# 创建一个QT数据库客户端
db = QSqlDatabase.addDatabase("QMYSQL")
# 设置host
db.setHostName("localhost")
# 设置端口号
db.setPort(3306)
# 设置连接用户名
db.setUserName("admin")
# 设置连接的密码
db.setPassword("123456")
# 设置连接的数据库名称
db.setDatabaseName("itheima")
# 打开数据库
db.open()
self.tableModel = QSqlTableModel(db=db)
self.tableModel.setTable("student")
self.tableModel.setEditStrategy(QSqlTableModel.OnFieldChange)
self.tableModel.setHeaderData(0,Qt.Horizontal,"学号")
self.tableModel.setHeaderData(1,Qt.Horizontal,"姓名")
self.tableModel.setHeaderData(2,Qt.Horizontal,"年龄")
self.tableModel.setHeaderData(3,Qt.Horizontal,"性别")
# 将封装好的模型交给tableWidget
self.tableView.setModel(self.tableModel)
def query_db(self):
print(self.tableModel.lastError().text())
self.tableModel.select()
def add(self):
self.tableModel.insertRow(self.tableModel.rowCount())
def delete(self):
# 找到当前选中行的下标
index = self.tableView.currentIndex().row()
self.tableModel.removeRow(index)
self.tableModel.select()
|