欢迎光临
我们一直在努力

Python + MySQL 学生信息管理系统实战教程

目录

  • 1. 项目概述
  • 2. 环境准备与数据库设计
    • 2.1 所需环境
    • 2.2 数据库表结构
  • 3. 核心代码实现
    • 3.1 数据库连接配置
    • 3.2 主程序与菜单
    • 3.3 查询功能实现
      • 3.3.1 查询全部学生信息
      • 3.3.2 根据学号查询学生信息
      • 3.3.3 搜索学生信息
    • 3.4 添加学生信息
    • 3.5 修改学生信息
    • 3.6 删除学生信息(软删除)
    • 3.7 主循环与菜单选择
  • 4. 系统特点与优化建议
    • 4.1 系统特点
    • 4.2 优化建议
  • 5. 总结
    • 5.1 完整代码文件
  • 6. 代码优化
    • 6.1 优化思路分析
      • 6.1.1 功能分离与代码复用
      • 6.1.2 动态字段修改
    • 6.2 优化代码详解
      • 6.2.1 新增的辅助函数
      • 6.2.2 重构后的主函数
    • 6.3 优化带来的好处
      • 6.3.1 代码可维护性提升
      • 6.3.2 用户体验改善
      • 6.3.3 扩展性增强
    • 6.4 进一步优化建议
      • 6.4.1 输入验证增强
      • 6.4.2 异常处理完善
      • 6.4.3 支持批量修改
    • 6.5 总结
    • 6.6 优化后的代码文件

1. 项目概述

本文将介绍一个基于 Python 和 MySQL 的简单学生信息管理系统。该系统实现了学生信息的增删改查(CRUD)功能,采用命令行交互方式,适合初学者学习 Python 数据库编程和基础系统开发。

系统主要功能包括:

  • 查询全部学生信息
  • 添加新学生
  • 修改学生信息
  • 删除学生(软删除)
  • 按学号搜索学生

2. 环境准备与数据库设计

2.1 所需环境

  • Python 3.x
  • PyMySQL 库(pip install pymysql)
  • MySQL 数据库

2.2 数据库表结构

首先创建数据库和表结构:

CREATE DATABASE IF NOT EXISTS abc;
USE abc;

CREATE TABLE `s1` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
`s_name` varchar(20) NOT NULL COMMENT '姓名',
`age` int NOT NULL COMMENT '年龄',
`sex` enum('男','女','未知') DEFAULT '未知' COMMENT '性别',
`s_sno` char(12) NOT NULL COMMENT '学号',
`tel` char(11) NOT NULL COMMENT '手机号',
`start_time` date DEFAULT (curdate()) COMMENT '入学时间',
`status` enum('在读','毕业') DEFAULT '在读' COMMENT '状态',
`id_card` char(18) DEFAULT NULL COMMENT '身份证号',
PRIMARY KEY (`id`),
UNIQUE KEY `s_name` (`s_name`),
UNIQUE KEY `s_sno` (`s_sno`),
KEY `name` (`s_name`),
KEY `name_age` (`s_name`,`age`),
FULLTEXT KEY `name_fulltext` (`s_name`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

3. 核心代码实现

3.1 数据库连接配置

import pymysql

# 创建数据库连接
db = pymysql.connect(
host="localhost",
user="root",
password="123456",
database="abc"
)

# 创建游标对象,采用字典模式
# 默认是元组模式,采用字典模式后可以通过 data['name'] 等方式取值
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)

3.2 主程序与菜单

# 主程序提示
tip = """
================================
欢迎使用【学生信息管理系统】
====================================
【1】查询全部学生
【2】添加学生
【3】修改学生
【4】删除学生
【5】搜索学生
【6】退出
请输入:"""

3.3 查询功能实现

3.3.1 查询全部学生信息

def seachAll():
sql = "select * from s1 where status = '在读'"
cursor.execute(sql)
data = cursor.fetchall()
print("编号 姓 名 \\t学 号\\t\\t 年龄\\t 性别\\t 联系方式\\t\\t\\t 身份证号")
for item in data:
print(f"{item['id']}\\t{item['s_name']}\\t\\t{item['s_sno']}\\t\\t{item['age']}\\t\\t{item['sex']}\\t\\t{item['tel']}\\t\\t\\t{item['id_card']}")

3.3.2 根据学号查询学生信息

def seachBySno(sno):
sql = "select * from s1 where status = '在读' and s_sno = %s limit 1"
cursor.execute(sql, (sno,)) # 元组,(sno,)是为了匹配SQL语句中字段,同时确保类型为元组
return cursor.fetchone()

3.3.3 搜索学生信息

def seach():
print("==========搜索学生信息=========")
sno = input("请输入学生学号:")
data = seachBySno(sno)
if data:
print(data)
else:
print("没有此学生")

3.4 添加学生信息

def addStudent():
print("==========添加学生信息=========")
sname = input("请输入学生姓名:")
sno = input("请输入学生学号:")
data = seachBySno(sno)
if data:
print("学号已存在")
return # 返回退出,下面的逻辑不执行

age = int(input("请输入学生年龄:")) # 年龄字段与数据库字段类型一致
if age <= 0 or age > 130:
print("年龄输入错误")
else:
sex = input("请输入学生性别:")
tel = input("请输入学生联系方式:")
# idCard = input("请输入学生身份证号:")

sql = "insert into s1(s_name,age,sex,s_sno,tel) values (%s,%s,%s,%s,%s)"
values = (sname, age, sex, sno, tel) # 元组,注意顺序与SQL语句中字段顺序一致
cursor.execute(sql, values)
db.commit()

if cursor.rowcount == 1:
print(f"添加{sname}成功")
else:
print(f"添加{sname}失败")

3.5 修改学生信息

def updateStudent():
print("==========修改学生信息=========")
sno = input("请输入学生学号:")
if seachBySno(sno):
sname = input("请输入学生姓名:")
age = int(input("请输入学生年龄:"))
if age <= 0 or age > 130:
print("年龄输入错误")
return # 返回退出,下面的逻辑不执行

sex = input("请输入学生性别:")
tel = input("请输入学生联系方式:")

sql = "update s1 set s_name = %s,age = %s,sex = %s,tel = %s where s_sno = %s"
values = (sname, age, sex, tel, sno)
cursor.execute(sql, values)
db.commit()

if cursor.rowcount == 0 or cursor.rowcount == 1:
print("修改成功")
else:
print("修改失败")
else:
print("没有此学生")

3.6 删除学生信息(软删除)

def deleteStudent():
print("==========删除学生信息=========")
sno = input("请输入学生学号:")
data = seachBySno(sno)
if data:
print(data)
confirm = input("确定删除吗?y/n:")
if confirm == "y" or confirm == "Y":
sql = "update s1 set status = '毕业' where s_sno = %s"
cursor.execute(sql, (sno,))
db.commit()
print("删除成功!")
else:
print("取消删除!")
else:
print("没有此学生")

3.7 主循环与菜单选择

while True:
print(tip)
choice = input().strip()

match choice:
case "1":
print("==========查询全部学生=========")
seachAll()
case "2":
print("==========添加学生信息=========")
addStudent()
case "3":
print("==========修改学生信息=========")
updateStudent()
case "4":
print("==========删除学生信息=========")
deleteStudent()
case "5":
print("==========搜索学生===========")
seach()
case "6":
print("==========退出===========")
break

4. 系统特点与优化建议

4.1 系统特点

  • 软删除设计:删除操作实际上是将学生状态改为"毕业",保留了历史数据
  • 输入验证:对年龄进行了范围验证(0-130岁)
  • 唯一性约束:学号和姓名在数据库层面设置了唯一约束
  • 字典游标:使用 pymysql.cursors.DictCursor 方便数据访问
  • 4.2 优化建议

  • 异常处理:添加数据库操作异常处理(try-except)
  • 密码安全:数据库密码不应硬编码在代码中
  • 功能扩展:可添加批量导入导出、统计报表等功能
  • 界面优化:可考虑使用 GUI 界面(如 Tkinter)替代命令行
  • 5. 总结

    本系统展示了如何使用 Python 和 MySQL 构建一个简单的学生信息管理系统。通过这个项目,可以学习到:

    • Python 连接 MySQL 数据库的基本操作
    • 使用 PyMySQL 库执行 SQL 语句
    • 实现基本的 CRUD 功能
    • 数据库表设计和约束的使用
    • 命令行交互程序的设计

    代码结构清晰,适合初学者学习和扩展。读者可以根据自己的需求进一步优化和完善系统功能。

    5.1完整代码文件

    import pymysql
    # 创建数据库连接
    db = pymysql.connect(
    host="localhost",
    user="root",
    password="123456",
    database="abc"
    )
    # 创建游标对象 可以实现 增删改查 cursor=pymysql.cursors.DictCursor采用字典模式,
    # 默认是元组模式,后续可以data['name']等进行取值
    cursor = db.cursor(cursor=pymysql.cursors.DictCursor)

    from project.database import db,cursor

    # 主程序提示
    tip = """
    ================================欢迎使用【学生信息管理系统】====================================
    【1】查询全部学生
    【2】添加学生
    【3】修改学生
    【4】删除学生
    【5】搜索学生
    【6】退出
    请输入:
    """

    # 查询全部学生信息
    def seachAll():
    sql ="select * from s1 where status = '在读'"
    cursor.execute(sql)
    data = cursor.fetchall()
    print("编号 姓 名 \\t学 号\\t\\t 年龄\\t 性别\\t 联系方式\\t\\t\\t 身份证号")
    for item in data:
    print(f"{item['id']}\\t{item['s_name']}\\t\\t{item['s_sno']}\\t\\t{item['age']}\\t\\t{item['sex']}\\t\\t{item['tel']}\\t\\t\\t{item['id_card']}")
    # 搜索学生信息
    # def seachOne():
    # sql ="select * from s1 where status = '在读' and s_name = %s limit 1" # limit 1避免获取多条数据以及浪费时间
    # sname = input("请输入学生姓名:")
    # cursor.execute(sql,sname)
    # data = cursor.fetchone()
    # print("编号 姓 名 学 号 年龄 性别 联系方式 身份证号")
    # print(data['id'],data['s_name'],data['s_sno'],data['age'],data['sex'],data['tel'],data['id_card'])。

    # 根据学号查询学生信息
    def seachBySno(sno):
    sql = "select * from s1 where status = '在读' and s_sno = %s limit 1"
    cursor.execute(sql,(sno,)) # 元组,(sno,)是为了匹配SQL语句中字段,同时确保类型为元组,而不是原本的类型
    return cursor.fetchone()
    # 查询学生信息
    # 查询学生信息
    def seach():
    print("==========搜索学生信息=========")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print(data)
    else:
    print("没有此学生")

    # 添加学生信息
    def addStudent():
    print("==========添加学生信息=========")
    sname = input("请输入学生姓名:")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print("学号已存在")
    return # 返回退出,下面的逻辑不执行
    age = int(input("请输入学生年龄:")) # 年龄字段与数据库字段类型一致,匹配数据库字段类型
    if age<=0 or age>130:
    print("年龄输入错误")
    else:
    sex = input("请输入学生性别:")
    tel = input("请输入学生联系方式:")
    #idCard = input("请输入学生身份证号:")
    sql = "insert into s1(s_name,age,sex,s_sno,tel) values (%s,%s,%s,%s,%s)"
    values = (sname, age, sex, sno, tel) # 元组,注意顺序与SQL语句中字段顺序一致
    cursor.execute(sql, values)
    db.commit()
    if(cursor.rowcount == 1):
    print(f"添加{sname}成功")
    else:
    print(f"添加{sname}失败")

    # 删除学生信息——-软删除
    def deleteStudent():
    print("==========删除学生信息=========")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print(data)
    confirm = input("确定删除吗?y/n:")
    if confirm == "y" or confirm == "Y":
    sql = "update s1 set status = '毕业' where s_sno = %s"
    cursor.execute(sql,(sno,))
    db.commit()
    print("删除成功!")
    else:
    print("取消删除!")
    else:
    print("没有此学生")

    # 修改学生信息
    def updateStudent():
    print("==========修改学生信息=========")
    sno = input("请输入学生学号:")
    if seachBySno(sno):
    sname = input("请输入学生姓名:")
    age = int(input("请输入学生年龄:"))
    if age<=0 or age>130:
    print("年龄输入错误")
    return # 返回退出,下面的逻辑不执行
    sex = input("请输入学生性别:")
    tel = input("请输入学生联系方式:")
    sql = "update s1 set s_name = %s,age = %s,sex = %s,tel = %s where s_sno = %s"
    values = (sname, age, sex, tel, sno)
    cursor.execute(sql, values)
    db.commit()
    if(cursor.rowcount == 0 or cursor.rowcount == 1):
    print("修改成功")
    else:
    print("修改失败")
    else:
    print("没有此学生")

    while True:
    print(tip)
    choice = input().strip()
    match choice:
    case"1":
    print("==========查询全部学生=========")
    seachAll()
    case"2":
    print("==========添加学生信息=========")
    addStudent()
    case"3":
    print("==========修改学生信息=========")
    updateStudent()
    case"4":
    print("==========删除学生信息=========")
    deleteStudent()
    case"5":
    print("==========搜索学生===========")
    seach()
    case"6":
    print("==========退出==============")
    break
    case _:
    print("输入错误,请重新输入:")

    6.代码优化

    6.1 优化思路分析

    在原始代码的基础上,我们对修改学生信息功能进行了重构和优化,主要改进点如下:

    6.1.1 功能分离与代码复用

    原始代码中,updateStudent() 函数负责所有修改逻辑,包括:

    • 学号验证
    • 用户输入
    • SQL 语句构建
    • 数据库更新
    • 结果反馈

    优化后的代码将核心的数据库更新操作提取为独立的 updateStudentChoice() 函数,实现了单一职责原则。

    6.1.2 动态字段修改

    原始代码只能同时修改所有字段(姓名、年龄、性别、联系方式),而优化后的代码允许用户选择要修改的特定字段,提高了系统的灵活性和用户体验。

    6.2 优化代码详解

    6.2.1 新增的辅助函数

    # 修改学生信息的选择方法
    def updateStudentChoice(data, file, sno):
    sql = f"update s1 set {file} = %s where s_sno = %s" # %s为占位符,这里使用{file}来代替实际字段名
    cursor.execute(sql, (data, sno))
    db.commit()
    if (cursor.rowcount == 0 or cursor.rowcount == 1):
    print("修改成功")
    else:
    print("修改失败")

    优化点分析:

  • 参数化设计:函数接收三个参数:

    • data:要更新的新值
    • file:数据库字段名
    • sno:学生学号(作为更新条件)
  • 动态 SQL 构建:使用 f-string 动态构建 SQL 语句,{file} 会根据传入的字段名动态替换

  • 简化逻辑:只执行单一的更新操作,逻辑更清晰

  • 6.2.2 重构后的主函数

    # 修改学生信息(可选择)————————-代码优化2——提炼公共信息到方法里
    def updateStudent():
    print("==========修改学生信息=========")
    sno = input("请输入学生学号:")
    if seachBySno(sno):
    nums = input("请输入修改的字段:1.姓名 2.年龄 3.性别 ")
    filds = ["s_name", "age", "sex"]
    values = ['姓名', '年龄', '性别']
    file = filds[int(nums)1]
    if nums in ['1', '2', '3']:
    data = input(f"请输入学生{values[int(nums)1]}:")
    updateStudentChoice(data, file, sno)
    else:
    print("输入错误")
    else:
    print("没有此学生")

    优化点分析:

  • 菜单化选择:提供清晰的字段选择菜单(1.姓名 2.年龄 3.性别)

  • 映射关系设计:

    • filds 列表:存储数据库字段名
    • values 列表:存储用户友好的显示名称
    • 通过索引建立两个列表的对应关系
  • 输入验证:检查用户输入是否在有效范围内(‘1’, ‘2’, ‘3’)

  • 函数调用:将具体的更新操作委托给 updateStudentChoice() 函数

  • 6.3 优化带来的好处

    6.3.1 代码可维护性提升
    • 分离关注点:updateStudent() 负责用户交互和输入验证,updateStudentChoice() 负责数据库操作
    • 减少重复代码:如果需要添加新的可修改字段,只需扩展 filds 和 values 列表
    • 易于测试:每个函数功能单一,便于单元测试
    6.3.2 用户体验改善
    • 选择性修改:用户可以选择只修改特定字段,无需重新输入所有信息
    • 操作更灵活:避免了不必要的重复输入
    • 错误减少:减少了因输入多个字段可能导致的错误
    6.3.3 扩展性增强

    # 未来可以轻松扩展更多字段
    filds = ["s_name", "age", "sex", "tel", "id_card"]
    values = ['姓名', '年龄', '性别', '联系方式', '身份证号']
    # 只需修改这两个列表,无需改动核心逻辑

    6.4 进一步优化建议

    6.4.1 输入验证增强

    # 可以添加更严格的输入验证
    def validate_age(age_str):
    try:
    age = int(age_str)
    if 0 < age <= 130:
    return age
    else:
    return None
    except ValueError:
    return None

    def validate_sex(sex_str):
    return sex_str if sex_str in ['男', '女', '未知'] else None

    6.4.2 异常处理完善

    def updateStudentChoice(data, file, sno):
    try:
    sql = f"update s1 set {file} = %s where s_sno = %s"
    cursor.execute(sql, (data, sno))
    db.commit()
    if cursor.rowcount == 1:
    print("修改成功")
    return True
    else:
    print("未找到对应记录或数据未变化")
    return False
    except Exception as e:
    print(f"修改失败: {e}")
    db.rollback()
    return False

    6.4.3 支持批量修改

    def updateMultipleFields(sno, updates_dict):
    """批量修改多个字段"""
    if not updates_dict:
    return False

    set_clause = ", ".join([f"{field} = %s" for field in updates_dict.keys()])
    values = list(updates_dict.values()) + [sno]

    sql = f"update s1 set {set_clause} where s_sno = %s"
    # … 执行更新

    6.5 总结

    本次优化主要实现了:

  • 函数职责分离:将用户交互和数据库操作分离
  • 动态字段选择:允许用户选择要修改的特定字段
  • 代码复用:提取公共逻辑到独立函数
  • 可扩展性:通过列表映射轻松添加新字段
  • 这种优化模式不仅适用于学生信息管理系统,也可以应用到其他需要类似 CRUD 操作的管理系统中。通过合理的函数拆分和参数化设计,可以显著提高代码的可维护性和用户体验。

    6.6优化后的代码文件

    from project.database import db,cursor

    # 主程序提示
    tip = """
    ================================欢迎使用【学生信息管理系统】====================================
    【1】查询全部学生
    【2】添加学生
    【3】修改学生
    【4】删除学生
    【5】搜索学生
    【6】退出
    请输入:
    """

    # 查询全部学生信息
    def seachAll():
    sql ="select * from s1 where status = '在读'"
    cursor.execute(sql)
    data = cursor.fetchall()
    print("编号 姓 名 \\t学 号\\t\\t 年龄\\t 性别\\t 联系方式\\t\\t\\t 身份证号")
    for item in data:
    print(f"{item['id']}\\t{item['s_name']}\\t\\t{item['s_sno']}\\t\\t{item['age']}\\t\\t{item['sex']}\\t\\t{item['tel']}\\t\\t\\t{item['id_card']}")

    # 根据学号查询学生信息
    def seachBySno(sno):
    sql = "select * from s1 where status = '在读' and s_sno = %s limit 1"
    cursor.execute(sql,(sno,)) # 元组,(sno,)是为了匹配SQL语句中字段,同时确保类型为元组,而不是原本的类型
    return cursor.fetchone()
    # 查询学生信息
    def seach():
    print("==========搜索学生信息=========")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print(data)
    else:
    print("没有此学生")

    # 添加学生信息
    def addStudent():
    print("==========添加学生信息=========")
    sname = input("请输入学生姓名:")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print("学号已存在")
    return # 返回退出,下面的逻辑不执行
    age = int(input("请输入学生年龄:")) # 年龄字段与数据库字段类型一致,匹配数据库字段类型
    if age<=0 or age>130:
    print("年龄输入错误")
    else:
    sex = input("请输入学生性别:")
    tel = input("请输入学生联系方式:")
    #idCard = input("请输入学生身份证号:")
    sql = "insert into s1(s_name,age,sex,s_sno,tel) values (%s,%s,%s,%s,%s)"
    values = (sname, age, sex, sno, tel) # 元组,注意顺序与SQL语句中字段顺序一致
    cursor.execute(sql, values)
    db.commit()
    if(cursor.rowcount == 1):
    print(f"添加{sname}成功")
    else:
    print(f"添加{sname}失败")

    # 删除学生信息——-软删除
    def deleteStudent():
    print("==========删除学生信息=========")
    sno = input("请输入学生学号:")
    data = seachBySno(sno)
    if data:
    print(data)
    confirm = input("确定删除吗?y/n:")
    if confirm == "y" or confirm == "Y":
    sql = "update s1 set status = '毕业' where s_sno = %s"
    cursor.execute(sql,(sno,))
    db.commit()
    print("删除成功!")
    else:
    print("取消删除!")
    else:
    print("没有此学生")

    # 修改学生信息的选择方法
    def updateStudentChoice(data,file,sno):
    sql = f"update s1 set {file} = %s where s_sno = %s" # %s为占位符,这里使用{file}来代替实际字段名
    cursor.execute(sql, (data,sno))
    db.commit()
    if (cursor.rowcount == 0 or cursor.rowcount == 1):
    print("修改成功")
    else:
    print("修改失败")
    # 修改学生信息(可选择)————————-代码优化2——提炼公共信息到方法里
    def updateStudent():
    print("==========修改学生信息=========")
    sno = input("请输入学生学号:")
    if seachBySno(sno):
    nums = input("请输入修改的字段:1.姓名 2.年龄 3.性别 ")
    filds = ["s_name","age","sex"]
    values = ['姓名','年龄', '性别']
    file = filds[int(nums)1]
    if nums in ['1','2','3']:
    data = input(f"请输入学生{values[int(nums)1]}:")
    updateStudentChoice(data, file, sno)
    else:
    print("输入错误")
    else:
    print("没有此学生")

    while True:
    print(tip)
    choice = input().strip()
    match choice:
    case"1":
    print("==========查询全部学生=========")
    seachAll()
    case"2":
    print("==========添加学生信息=========")
    addStudent()
    case"3":
    print("==========修改学生信息=========")
    updateStudent()
    case"4":
    print("==========删除学生信息=========")
    deleteStudent()
    case"5":
    print("==========搜索学生===========")
    seach()
    case"6":
    print("==========退出==============")
    break
    case _:
    print("输入错误,请重新输入:")

    赞(0)
    未经允许不得转载:171主机测评 » Python + MySQL 学生信息管理系统实战教程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址