news 2026/9/10 11:14:45

Python课程设计:田径运动会管理系统源码深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python课程设计:田径运动会管理系统源码深度解析

简介:这是一份Python课程设计田径运动会管理系统源码与数据库打包,面向需要完成数据库或Python课程设计的高校学生,提供了一套可直接运行的运动会管理项目。压缩包共35个文件、约11.24MB,包含4个.py源码、1个.sql数据库脚本、3个.xlsx运动员及成绩数据表;另附可直接运行的exe客户端、pyc编译文件与15张功能界面截图,覆盖登录、信息查询、成绩录入、项目分组、名次排名等核心模块。目前已有280人学习下载。项目源码清晰分离了数据库操作、Tkinter图形界面与业务逻辑三个部分,可学习如何设计运动员表、项目表、成绩表和排名表之间的关联,以及成绩录入、排名计算等功能的实现;配合演示Excel与Visual Studio工程文件,便于快速运行、调试和二次开发,是课程设计展示和Python数据库实战入门的理想资料。

1. 从登录框到成绩单,这套课设代码最值钱的是数据链路

接手一套课程设计代码,最怕的不是界面丑,而是答辩时被问到"成绩排名怎么算出来的""删掉一个运动员之后成绩表会怎样"这类数据链路问题就卡壳。田径运动会管理系统这套源码,把最常见的业务场景完整走了一遍:登录需要账号表校验,运动员信息要支持编号和姓名两种查询方式,录入成绩要同时校验运动员表和项目表,名次不能手填而是由排序逻辑生成,最后还要按学院出汇总报表。从压缩包里的文件列表可以清晰看出这是个分层项目——DBclass.py 负责数据库操作、GUI.py 负责界面交互、client.py 是启动入口、createCD.sql 是建表脚本,旁边还配了 Excel 示例数据和已打包好的 client.exe。正在找 Python 课程设计参考的人,可以拿着它直接跑通流程;想把这套骨架改成仓库管理、图书管理等其他场景的开发者,也能从表结构和统计逻辑里直接复用经验。

2. 文件结构反推架构:DBclass 负责连接,GUI 负责交互

2.1 源码包里的文件到底在做什么

解压压缩包之后先别急着双击 exe,把文件和目录过一遍,架构图基本就出来了。这个项目的文件组织非常典型,是一个"入口 — 界面 — 数据层"三件套结构,我把关键文件整理成了下面的对应关系。

文件职责推断判断依据
client.py程序启动入口有同名 client.spec,说明打包入口是它
GUI.py图形界面与事件绑定截图里的登录界面、功能选择界面都对应这里的窗口类
DBclass.py数据库连接与 SQL 封装类名直接是 DB,提供查询和写入方法
account_information_entry.py管理员账号信息入口登录界面和账号表的校验逻辑会调用它
createCD.sqlMySQL 建库建表脚本.sql 后缀,包含建库和 create table 语句
运动员信息.xlsx运动员基础数据示例界面"添加运动员信息"和批量导入共用这个格式
运动员成绩.xlsx成绩数据导出模板成绩单导出时按这个结构写 Excel
demo.xlsx演示用数据集空库时导入它可以直接演示全部功能
client.exe已打包的可执行文件PyInstaller 产物,运行不需要安装 Python
登录失败.png / 查无此人.png异常分支截图说明项目里做了失败提示,不是只画了主流程

这里有一个容易被忽略的细节:__pycache__里全部是.cpython-310.pyc,说明源码是在 Python 3.10 环境下编译运行的。如果你本机是 3.8 或者 3.11,直接跑 client.py 一般没问题,但如果重新打包 exe,建议统一到 3.10,避免第三方依赖在不同版本下行为不一致。

2.2 DBclass.py 里的数据库连接设计

数据层是整套系统的地基。虽然文件名只是简单的 DBclass,但它承担了连接管理、SQL 执行、事务提交三件事。常见做法是用 PyMySQL 连接 MySQL,连接参数集中写在类初始化方法里。

import pymysql class DB: def __init__(self, host="localhost", user="root", password="123456", database="track_meet"): self.conn = pymysql.connect( host=host, user=user, password=password, database=database, charset="utf8mb4", cursorclass=pymysql.cursors.DictCursor ) def query(self, sql, args=None): with self.conn.cursor() as cursor: cursor.execute(sql, args) return cursor.fetchall() def execute(self, sql, args=None): with self.conn.cursor() as cursor: affected = cursor.execute(sql, args) self.conn.commit() return affected

四个连接参数是最容易踩坑的地方:host 默认写 127.0.0.1 只能连本机 MySQL,客户机上如果数据库跑在另一台服务器,这里要改成对应 IP;password 要和本地 MySQL 实际密码一致,课设代码里默认的 123456 十有八九和你环境对不上;database 名称必须与 createCD.sql 里的建库语句同名,否则报Unknown database;charset 建议锁死 utf8mb4,否则导入 Excel 里的中文姓名会乱码。

queryexecute两个方法的返回值设计值得学习:查询返回字典列表,写入返回受影响行数。界面层判断"到底插进去没有"时,直接看 execute 的返回值,大于 0 才弹"添加成功",比 try-except 硬扛要清晰得多。这套封装对课程设计来说刚好,既不臃肿又能应付增删改查。

2.3 GUI.py 与业务逻辑的耦合

GUI.py 用的是 Tkinter,这是 Python 自带的标准库,不需要额外安装第三方界面框架。它的逻辑是拿到 db 对象,把数据库操作直接嵌在按钮回调里,典型写法如下:

import tkinter as tk from tkinter import ttk, messagebox from DBclass import DB class MainWindow: def __init__(self, db): self.db = db self.root = tk.Tk() self.root.title("田径运动会管理系统") self.keyword = tk.StringVar() def search_athlete(self): keyword = self.keyword.get().strip() sql = ("SELECT no, name, college FROM athlete " "WHERE no LIKE %s OR name LIKE %s") rows = self.db.query(sql, (f"%{keyword}%", f"%{keyword}%")) if not rows: messagebox.showwarning("提示", "查无此人") else: self.show_result(rows)

界面层直接用%s占位符做参数化查询,把用户输入当作参数传给 execute,而不是拼进 SQL 字符串,这个习惯挡住了 SQL 注入。截图里会看到"编号或姓名.png"和"姓名查询.png"两张图,对应的就是LIKE匹配的两条路径——输入纯数字时可以走编号精确匹配,输入中文时走姓名模糊匹配,界面共用一个输入框,底层 SQL 用 OR 连接。

需要注意 Tkinter 的 StringVar 要在变量绑定控件前创建,否则控件拿不到字符串变量的引用,输入框内容永远是空字符串。很多课设代码在输入框里怎么输都查不到结果,问题往往出在这一行。

3. createCD.sql 里的表关系与名次计算路径

3.1 四张表撑起一个运动会

打开 createCD.sql,核心是四张业务表的设计。我按字段职责把它们拆开看,关系非常清楚。

表名关键字段作用
accountaccount_no, password管理员登录账号
athleteno, name, college, gender运动员基本信息
eventevent_no, event_name比赛项目字典表
scoreid, athlete_no, event_no, score, rank成绩记录与名次

运动员表和项目表是字典数据,成绩表是关系数据。一条成绩记录必须同时关联一个运动员和一个项目,所以 score 表里 athlete_no 和 event_no 都设置成外键。

CREATE TABLE score ( id INT PRIMARY KEY AUTO_INCREMENT, athlete_no VARCHAR(20) NOT NULL, event_no INT NOT NULL, score DECIMAL(8, 2) NOT NULL, rank INT DEFAULT NULL, FOREIGN KEY (athlete_no) REFERENCES athlete(no), FOREIGN KEY (event_no) REFERENCES event(event_no) );

score 字段用 DECIMAL(8,2) 而不是 FLOAT,是因为田径成绩有大量精确到百分之一秒的径赛数据,FLOAT 在反复比较时会产生浮点误差,DECIMAL 是定点数,排序和相等判断都稳定。rank字段允许为空,在成绩尚未录入完时保留 NULL,只有排名计算跑过之后才填充。外键约束的意义在于:录入成绩时如果运动员编号不存在,数据库直接拒绝写入,这比在 Python 里先查一次再插入要可靠得多。

3.2 成绩录入为什么要做项目分组校验

界面截图里有一张"输入运动员参加的项目编号.png",这个设计就是为了校验运动员和项目的对应关系。一个运动员可以报名多个项目,但一个运动员在同一个项目里只能有一条成绩,否则排名统计会出现重复数据。所以插入成绩时不能只插 athlete_no 和 event_no,还要先查一遍运动员是否报名该项目。

SELECT COUNT(*) FROM registration WHERE athlete_no = %s AND event_no = %s;

如果没有 registration 表,退一步的做法是在 score 表上建联合唯一索引,用数据库兜底保证同一运动员同一项目只能有一条成绩记录。这个索引在成绩录入场景下还有一个附带好处:按运动员查成绩单、按项目排名次都走这个索引,查询速度会明显快于全表扫描。

3.3 名次计算:一条 UPDATE 搞定窗口函数排序

名次是管理系统里最容易做成反面教材的功能。很多课程设计里是查到成绩后在 Python 里排序循环,再逐条 UPDATE 回数据库,数据量小的时候看不出问题,一旦同一项目有几百条成绩,循环更新既慢又容易在中间出错。正确做法是把排名计算放到数据库里,用一条 UPDATE 加上窗口函数完成。

UPDATE score s JOIN ( SELECT athlete_no, event_no, RANK() OVER (PARTITION BY event_no ORDER BY score ASC) AS rk FROM score ) t ON s.athlete_no = t.athlete_no AND s.event_no = t.event_no SET s.rank = t.rk;

这段 SQL 的逻辑核心是RANK() OVER (PARTITION BY event_no ORDER BY score ASC)。PARTITION BY 表示按项目编号分组,每个项目内部独立排名;ORDER BY score ASC 表示成绩数值越小排名越靠前,适用于径赛短跑这类"用时少者胜"的项目。如果是跳远、铅球这类田赛项目,成绩越大越好,把 ORDER BY 改成 DESC 即可。

RANK()DENSE_RANK()的差别在于并列名次:两个并列第一之后,RANK 会跳过第二名直接排第三,DENSE_RANK 则不会跳。对运动会场景来说 RANK 更合理,因为沉甸甸的奖牌榜里没有"第二名位置空缺"的说法。要注意的是窗口函数要求 MySQL 8.0 及以上版本,如果是 5.7 就得用用户变量来模拟分组排名,逻辑会绕一些。

3.4 学院成绩汇总的聚合查询

截图里有"学院成绩.png"和"输入学院信息.png",对应的是按学院统计总分的报表页面,SQL 落在两表 JOIN 加分组聚合上。

SELECT a.college, COUNT(DISTINCT s.athlete_no) AS athlete_count, SUM(s.score) AS total_score FROM athlete a JOIN score s ON a.no = s.athlete_no GROUP BY a.college ORDER BY total_score DESC;

这里有两个容易出错点。第一,COUNT 必须加 DISTINCT 限定到 athlete_no,因为一个运动员可能参加多个项目产生多条成绩记录,直接 COUNT(*) 会把总人数统计成总参赛人次。第二,SUM(s.score) 只对已录入的成绩生效,如果某个运动员缺考没有成绩记录,JOIN 结果里根本不会出现他,学院总分自然不包含缺考项。业务上如果要求缺考按 0 分计算,就得先 LEFT JOIN 再对 NULL 做 IFNULL 处理。

4. 登录鉴权、信息查询、成绩录入的完整流程拆解

4.1 登录失败不是界面问题,是账号表没初始化

压缩包里有一张"登录失败.png"的截图,这是相见恨晚的一张图。登录失败最常见的原因不是密码输错,而是 account 表里根本没有数据。createCD.sql 建完表之后是空表,你要先插入一条管理员记录,登录界面才有账号可验证。

INSERT INTO account (account_no, password) VALUES ('admin', 'admin123');

登录界面在真实的代码里要做两层判断:第一层是输入框非空校验,两个输入框任一个为空就直接提示"账号或密码不能为空",不发起数据库查询;第二层才查库比对账号和密码。比对时注意密码字段不要以明文形式展示在数据库中,课程设计级别可以用 hashlib 做一次 SHA-256 散列再存储。

import hashlib raw_password = "admin123" hashed = hashlib.sha256(raw_password.encode("utf-8")).hexdigest()

账号密码校验通过之后,界面才会销毁登录窗口,创建功能选择主窗口。这个流程对应截图里"登录界面.png"到"功能选择界面.png"的跳转关系。

4.2 编号或姓名查询的两种检索路径

"编号或姓名.png"和"姓名查询.png"两张截图暴露了查询功能的两种入口,在实现上共用同一个查询方法,靠 SQL 参数不同区分路径。如果输入是纯数字,优先走编号精确匹配;包含中文就按姓名模糊匹配。实际上用一个 OR 条件就能同时覆盖两个入口。

def search_athlete(self, keyword): sql = ("SELECT no, name, college, gender " "FROM athlete WHERE no = %s OR name LIKE %s") rows = self.db.query(sql, (keyword, f"%{keyword}%")) return rows

值得注意的细节是编号字段no在数据库里通常定义成 VARCHAR 而不是 INT,因为运动员编号可能带有前缀或前导零,用 INT 类型会把 "001" 存成 1,查询时前端传 "001" 反而匹配不上。这是一个典型的"看着能跑但数据不对"的坑,课程设计代码里保留字符串类型,说明作者踩过这个坑。

4.3 成绩录入界面与运动员成绩单的联动

"成绩录入界面.png"和"运动员成绩单.png"之间的关系,是录入和查询两条通路在数据层的交汇。录入成绩时,界面会提供运动员选择下拉框和项目选择下拉框,选完以后自动带入运动员编号,避免手工输入编号产生的格式错误。

实际代码里两个下拉框的数据源是两个独立的数据库查询:

athletes = self.db.query("SELECT no, name FROM athlete") events = self.db.query("SELECT event_no, event_name FROM event")

下拉框显示中文名,存储值绑定编号,这是 GUI 开发里最常见的"显示值与存储值分离"模式。Tkinter 的 ttk.Combobox 通过一个字典实现这个映射,选中运动员名字时拿到的是 athlete_no 而不是姓名文本。成绩录入完点保存后,Treeview 表格马上刷新,新纪录出现在"运动员成绩单"列表的底部,这个即时反馈依赖插入成功后重新执行一次 SELECT,而不是手动拼接界面数据。

4.4 成绩修改与删除的级联约束策略

成绩录错了要改,运动员退赛要删,这两件事都涉及 score 表的级联处理。score 表的外键如果设置了ON DELETE CASCADE,删除运动员时数据库会把他的所有成绩一并删除,应用层不需要写任何历史清理代码。

FOREIGN KEY (athlete_no) REFERENCES athlete(no) ON DELETE CASCADE

这对运动会管理系统是合理的策略:运动员信息删除后,保留他过去的成绩没有业务意义。但要注意报表页面最好对级联删除给用户一个二次确认,因为成绩一旦跟着删除,学院统计的总分也会立刻变化。界面上对应的做法是删除按钮回调里先弹 messagebox.askyesno,确认后才调用 DELETE 语句。

5. 用 PyInstaller 打包成 exe 与二次改造的三种做法

5.1 client.spec 透露的打包细节

压缩包里的 client.spec 是 PyInstaller 生成的打包配置文件,它决定了 exe 的入口、依赖和窗口属性。最简单的打包命令是下面这行,在 client.py 同级目录执行即可。

pyinstaller client.spec

spec 文件里的核心配置决定了产物形态:

a = Analysis( ['client.py'], pathex=['.'], hiddenimports=['pymysql', 'openpyxl'], noarchive=False, ) exe = EXE( pyz, a.scripts, exclude_binaries=True, name='田径运动会管理系统', console=False, )

console=False 是最容易忽略的参数之一。课程设计演示时如果控制台窗口和 GUI 窗口一起弹出来,观感很差,设成 False 可以只保留 GUI。调试时反过来,把它临时改成 True,PyMySQL 连接报错、未捕获异常都会打印在黑窗口里,定位问题比瞎猜快得多。

hiddenimports 里列出 pymysql 和 openpyxl 很关键。PyInstaller 静态分析 import 语句时,对通过字符串动态导入的模块会漏掉。pymysql 的 connections 模块和 openpyxl 的 reader 模块都是典型的动态导入目标,不写进 hiddenimports,打包出的 exe 运行到一半会报 ModuleNotFoundError,而且只在实际触发数据库连接或 Excel 导出的那一刻才暴露。

5.2 运行时报错的排查路径

拿到源码先别急着改功能,按下面的顺序把环境跑通,报错概率降一半。

  1. 先看 MySQL 服务有没有启动,Windows 下用net start mysql或服务管理器确认。
  2. 用命令行客户端测试连接:mysql -u root -p,密码不对就先用 root 登录改掉 DBclass.py 里的 password 参数。
  3. 登录 MySQL 后执行source createCD.sql建表,注意建库语句里的库名必须和 DBclass.py 的 database 参数严格一致。
  4. 插入初始管理员账号,否则登录界面永远弹"登录失败"。
  5. 双击 client.exe 前先在命令行运行client.exe,Windows 下 GUI 程序的报错信息会被吞掉,命令行里跑能看到 traceback。

双击 exe 没反应是最常见的打包问题,八成是上面第二步或者第四步没做完。命令行跑一下,错误信息会直接告诉你连不上数据库还是账号表为空。

5.3 把课设改成仓库管理系统的换皮思路

这套骨架并不只属于田径运动会。它的表结构本质是"主表 + 记录表 + 统计表"的通用模式,改造成其他管理系统的操作路径是从数据层往上换皮。

第一层改库。把 athlete 表改成 student 表或者 goods 表,把 no、name、college 三个字段换成业务对应的编号、名称、所属分类;event 表对应物料分类或课程列表;score 表对应库存变动或选课记录。第二层改 SQL。排名窗口函数换成库存汇总的SUM(quantity) GROUP BY goods_no,学院成绩统计换成按部门汇总的金额统计。第三层改界面。把 GUI.py 里的 Tkinter Label 文本和 Treeview 列名替换成新业务名词,项目分组下拉框的查询语句把SELECT event_no FROM event改成SELECT category_id FROM category,其余绑定逻辑原样保留。

换完以后用 demo.xlsx 造 100 条假数据,从登录到统计完整走一遍。能稳定输出结果,说明这套骨架已经接住了新业务。课程的答辩重点是排名计算的窗口函数和 Excel 导入的联动逻辑,这两块是数据库课程设计里最能体现能力深度的位置,讲清楚比堆界面有意义得多。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 11:13:23

用R做流行病学数据分析:从回归建模到生存分析实战指南

这本书我一定要推荐给所有想用R做流行病学数据分析的朋友。书名是Epidemiology with R,作者是Bendix Carstensen,牛津大学出版社出的,全英文。市面上讲R语言入门的书多如牛毛,但能真正把“流行病学问题”和“R代码实现”拧成一股绳…

作者头像 李华
网站建设 2026/9/10 11:13:08

广东10米土地覆盖数据解析:分类栅格的元数据与Python处理

简介:本资源为面向GIS研究者、遥感分析人员及城乡规划从业者的高精度广东土地覆盖数据集,解决区域生态评估、城市扩张监测、农业用地识别等空间分析需求。数据包含10米分辨率栅格与省级行政边界矢量两类核心地理信息:2个.tif主文件&#xff0…

作者头像 李华
网站建设 2026/9/10 11:12:25

家政返物业费小程序开发,服务缴费联动开发

家政返物业费小程序开发,服务缴费联动开发家政返物业费小程序的核心价值,在于实现家政服务消费与物业缴费场景的深度联动,打破家政交易、额度返还、物业费抵扣、账单核销的业务壁垒。传统社区家政小程序只独立支撑上门服务下单与支付功能&…

作者头像 李华
网站建设 2026/9/10 11:04:53

CANN/ge获取编译图概要信息API

GetCompiledGraphSummary 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、T…

作者头像 李华
网站建设 2026/9/10 11:04:33

Java大厂面试核心知识点与实战技巧解析

1. 互联网大厂Java面试现状剖析最近两年互联网行业招聘市场出现了一个有趣的现象:技术面试逐渐演变成了一场严肃面试官与搞笑程序员之间的"对决"。作为经历过数十场大厂面试的资深Java开发者,我发现这种看似戏剧化的场景背后,其实反…

作者头像 李华