在传统校园管理场景中,学生档案、课程安排和成绩记录常常分散在 Excel 表格与纸质文件里,查询一次信息往往需要在多个文档之间来回切换。使用Python、PyQt5和SQL搭建一套完整的学校管理系统,不只是一次桌面软件开发练习,更是对“如何用数据驱动校园管理”这一问题的工程化实践。

这类学校管理软件的核心架构通常采用经典的三层设计:表现层(PyQt5 GUI 图形界面)、业务逻辑层(Python负责请求处理与规则校验)、数据访问层(SQL数据库读写与存取)。这种分层结构能够有效实现界面与数据操作解耦,方便后续维护、功能扩展以及系统升级。
一、数据库设计:承载业务逻辑的基础
数据库设计直接决定了学校管理系统能管理哪些业务、以什么方式管理。从常见开源项目和实际开发经验来看,一套完整的学校管理系统通常包含以下核心数据表:
学生表(students) :用于存储学号(设 UNIQUE 防止重复)、姓名、性别、班级、联系方式、入学年份等字段。学号通常作为主键,是各类关联查询的重要依据。
教师表(teachers) :记录教师ID、姓名、所属院系、职称、联系电话等信息。教师与课程之间通常通过开课表建立关联。
课程表(courses) :包含课程ID、课程名称、学分、学时等基础信息。课程本身更像一个“模板”,具体到某学期的教学安排则由开课表承接。
开课表(course_offerings) :这是连接教师、课程与学期安排的关键表——记录哪门课在什么学期由哪位教师开设,以及上课时间、教室、最大选课人数等信息。开课表的存在使同一门课程能够在不同学期重复使用,减少数据冗余。
选课表(enrollments) :记录学生选了哪门开课课程,通常包含成绩字段(可空,成绩录入前为NULL)和选课时间。这往往是系统中数据量最大、增长速度最快的一张表。
用户表(users) :用于存储登录账号、密码哈希值、角色(admin/teacher/student)、关联外键ID(指向学生表或教师表)、账号状态(启用/禁用)以及最后登录时间。
用SQL建表的语句大致如下:
代码语言:ja vascript复制CREATE TABLE students (student_id VARCHAR(20) PRIMARY KEY,name VARCHAR(50) NOT NULL,gender CHAR(1),class_name VARCHAR(30),phone VARCHAR(20));CREATE TABLE users (user_id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) UNIQUE NOT NULL,password_hash VARCHAR(255) NOT NULL,role ENUM('admin', 'teacher', 'student') NOT NULL,ref_id VARCHAR(20),-- 指向student_id或teacher_idis_active BOOLEAN DEFAULT TRUE);
二、数据库连接层:统一管理数据库会话
PyQt5通过 QtSql 模块提供了对SQL数据库的原生支持。数据库连接层的封装应尽量做到:统一管理连接、在异常发生时给出清晰提示,并支持多种数据库驱动(MySQL使用 QMYSQL,SQLite使用 QSQLITE)。
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
def create_connection():
db = QSqlDatabase.addDatabase('QMYSQL')
db.setHostName('localhost')
db.setDatabaseName('school_db')
db.setUserName('root')
db.setPassword('your_password')
if not db.open():
print('数据库连接失败:', db.lastError().text())
return False
return True
对于本地部署、课程设计或毕业设计等场景,SQLite 往往是更轻量的方案——单文件存储、零配置、无需额外安装数据库服务。将数据库类型设置为可配置项,就能在 QMYSQL 与 QSQLITE 之间灵活切换,兼顾开发效率与生产环境下的性能需求。
三、登录与权限:不仅仅是“账号密码验证”
登录模块是整个学校管理软件的入口,也是权限控制的起点。一个健壮的登录模块通常需要完成三件事:
验证身份:查询users 表,比对用户名与密码哈希值,而不是保存明文密码。检查状态:确认账号未被禁用。记录审计:登录成功后更新 last_login 时间戳,并写入操作日志。登录成功后,系统会根据 role 字段决定进入不同主界面——管理员可查看完整的数据管理面板,教师可进入所授课程和成绩录入模块,学生则通常只能查看自己的成绩信息与课程表。
权限控制的关键不在于“登录后把按钮隐藏起来”,而在于从数据查询层面实现隔离。教师查询课表时自动追加 WHERE teacher_id = ?,学生查询成绩时自动追加 WHERE student_id = ?,这些过滤条件由登录态携带的用户信息在模块初始化阶段动态注入,安全性更高,也更符合实际项目开发规范。
四、核心CRUD:Model/View架构的优势
PyQt5的 QSqlTableModel 是操作数据库表的重要工具——它可以将数据库表直接映射为表格模型,天然支持自动同步、主键识别、事务回滚和内置编辑缓冲。配合 QTableView 使用时,可以实现“界面编辑即数据库更新”的效果,非常适合学校信息管理系统这类表格型业务。
from PyQt5.QtSql import QSqlTableModelfrom PyQt5.QtWidgets import QTableViewmodel = QSqlTableModel()model.setTable('students')model.setEditStrategy(QSqlTableModel.OnFieldChange)# 编辑即提交model.select()view = QTableView()view.setModel(model)
setEditStrategy 有三个选项:
OnFieldChange:单元格编辑完成后立即提交到数据库OnRowChange:行编辑完成后提交OnManualSubmit:手动调用 submitAll() 才提交对于学生信息管理这类高频操作,OnFieldChange 更直观、更高效;而对于成绩录入这类需要批量审核的业务场景,OnManualSubmit 更适合——教师录入完整行成绩后可统一提交,提交前也能随时撤销修改。
增删改查操作通常会封装在独立的业务模块中。例如 student.py 负责学生信息管理,grade.py 处理成绩录入与成绩查询,classes.py 管理班级列表。每项操作都应配合事务控制,例如删除学生时同步清理其选课记录,避免出现孤儿数据,保证数据库一致性。
五、实际项目结构参考
一个可以直接运行的PyQt5学校管理系统,目录结构通常如下:
代码语言:ja vascript