资讯动态

Python+MySQL宿舍管理系统课设实战:从数据库设计到答辩避坑

发布时间:2026/10/3 14:48:38 来源:尧图企业网站定制
简介这是一套基于Python与MySQL实现的学校宿舍管理网站系统面向高校及培训机构的日常宿舍管理场景同时适配毕业设计或课程设计项目需求。压缩包整体约8.09MB内含程序源代码、数据库设计脚本以及环境配置说明能够指导用户完成本地部署与系统运行。项目核心覆盖用户管理、宿舍分配、床位管理、信息查询与统计报表等功能模块后端由模型、视图、路由等结构构成配合前端模板实现完整交互流程。对于正在学习Python Web开发的学生而言该项目提供了从数据表设计到业务逻辑实现的完整闭环可深入理解Django/Flask框架与MySQL在实际应用中的协作方式。当前已有85人学习使用适合作为毕业设计或课程设计时的直接参考与二次开发基础。1. 宿舍管理网站系统能做什么Python MySQL 课设项目的真实交付形态答辩现场演示宿舍管理系统最常见的翻车方式是什么不是功能没写完而是数据库连不上、页面白屏、评委看着你一遍遍重启服务。基于Python MySQL实现学校宿舍管理网站系统就是这类毕设、课设的典型交付物后端用 Python 的 Web 框架处理登录、分配、查询这些业务请求MySQL 存业务数据前端用模板页面做展示。它解决的问题很具体——把学生的入住、退宿、调宿、报修、晚归这些宿舍日常管理动作全部搬到网页上替代纸质台账。这篇笔记的目标读者很清楚正在选毕设题目、想找一个业务闭环完整且能讲深讲透的学生或者想用一套全栈项目补充简历的在校生。下面按“选型→跑通→实现→排错→演示”一条线讲完。2. 选型与架构为什么课设默认 Flask MySQL而不是 Django 或 SQLite2.1 Flask 够用Django 太重SQLite 应付不了多表业务先解决一个几乎所有拿到这类题目的人都会纠结的问题标题只说“Python”到底用 Flask 还是 Django我经手的毕设项目里选 Flask 的比例远高于 Django不是 Flask 更高级而是宿舍管理系统这个业务的复杂度决定了 Flask 刚好压线。宿舍管理网站的核心是无非这几条链路登录鉴权、学生信息增删改查、宿舍分配与调宿、报修记录、统计报表。Flask 处理这类请求非常直接浏览器发一个 HTTP 请求过来Flask 根据路由找到对应的视图函数视图函数里执行 SQL 或调用封装好的数据库方法拿到结果后把数据填进 Jinja2 模板返回 HTML。这套链路没有任何需要 Flask 以外的东西才能解决的环节所以用它做得快、改得动。Django 在这类项目里不是不能用而是过度配置。Django 自带 admin 后台、ORM 迁移、中间件、认证体系看起来白拿一堆功能但代价是学习曲线陡第一次建项目要理解 settings 拆分、应用注册、模型迁移很多新手把环境跑通就已经花了别人跑通三个 Flask 项目的时间。如果导师的验收要求只是“系统能登录、能分配、能统计”我建议直接用 Flask如果导师明确要求体现工程规范、必须有管理后台再考虑 Django。至于为什么不选 SQLite直接原因就是题目点名了 MySQL选 SQLite 等于把需求改小。SQLite 是文件型数据库不需要启动服务对课设来说确实省事但涉及多人同时写入时它表现很差而且外键约束、事务隔离、用户权限这些在 MySQL 里很自然的功能SQLite 要么弱化要么套一层别扭的接口。另外一个现实原因是答辩现场很容易被问到“为什么不用 MySQL”用 SQLite 很难答出一二三来反过来用 MySQL你能顺势讲出表结构设计、事务、权限、备份这些加分点。2.2 数据库表设计五张核心表撑起宿舍管理的全部业务拿到一个课设项目先别急着跑代码先读数据库脚本。因为 SQL 文件会直接告诉你这个系统的业务边界只有两张表大概率是个登录壳子有五六张带外键的表才说明把入住、调宿、报修做进去了。结合宿舍管理的常见需求我一般会把表设计成这个结构表名职责关键字段说明user登录账号id, username, password, rolerole 区分 admin、manager、studentstudent学生档案id, student_no, name, gender, major, class_name, phone与 user 通过 student_no 关联dorm宿舍房间id, building, floor, room_no, capacitycapacity 表示床位总数occupancy住宿关系id, student_id, dorm_id, bed_no, check_in_date, check_out_datecheck_out_date 为空表示在住repair报修记录id, dorm_id, reporter, description, status, create_timestatus 用 0、1 表示未处理、已处理notice公告通知id, title, content, publish_time用于首页信息展示注意 occupancy 这张表它是整套系统的轴心。很多课设同学图省事把 dorm_id 直接挂在 student 表上看起来查询方便一旦出现“调宿留痕”“统计某个时间段内哪些人住过这间房”之类的需求就会发现同一张表里既存现状又存历史SQL 怎么写都别扭。拆出独立关系表之后“当前住宿”就是入住记录里 check_out_date 为空的那一条退宿就是把 check_out_date 更新为当前日期调宿就是关旧记录、插新记录这两步放在同一个事务里完成逻辑非常干净。status 这类状态字段建议统一用整数而不是字符串。MySQL 里字符串比较慢更重要的是容易写错大小写比如“Finished”和“finished”是两个值排查半天才发现是数据问题。用 0、1、2 这种枚举数字代码里用常量名引用比如 STATUS_PENDING 0既不会写错答辩时还能顺带讲一下状态机设计。2.3 拿到 zip 后怎么判断值不值得跑目录结构与改造顺序这类项目交付物是一个 zip 包很多人习惯先双击 main.py 或者直接敲 python app.py然后被各种报错劝退。正确顺序是先看目录结构一个可运行的 Flask MySQL 课设项目通常长这样dorm_system/ ├── app.py # Flask 入口注册所有路由 ├── config.py # MySQL 连接配置与密钥 ├── dorms.sql # 建库建表脚本与预置数据 ├── requirements.txt # 依赖清单 ├── utils.py # 公共函数数据库连接、登录校验 ├── templates/ # Jinja2 模板页面 │ ├── base.html │ ├── login.html │ ├── index.html │ └── dorm/ ├── static/ # CSS、JS、图片 └── README.md # 启动说明解压后我会依次看三样东西第一是 dorms.sql确认表数量和字段是否符合刚才说的业务线第二是 app.py 里注册的 URL 规则看看路由是否覆盖了登录、学生管理、宿舍分配、报修等核心功能第三是 config.py确认数据库连接方式写死在哪。这套顺序能在五分钟内判断出这个 zip 是能跑通的完整项目还是只做了个壳子套模板的拼凑品避免浪费时间在一个跑起来才发现什么功能都没有的项目上。还有一个细节值得注意requirements.txt 里的依赖版本。很多项目打包时不会锁版本直接写 flask、pymysql这种情况下你安装的可能不是作者当时用的版本接口差异会带来奇怪的报错。我自己接手课设项目时会把依赖装完后顺手固定版本至少保证自己能稳定复现。下一个章节就从环境准备开始把这些坑逐个排掉。3. 本地跑通全流程Python 安装、MySQL 建库与 Flask 启动的每一步3.1 环境版本选对后面少踩一半坑Python 3.8 配 MySQL 8.0跑这种项目之前先确认两个基础环境Python 和 MySQL。很多报错根本不是代码问题而是版本不匹配。Python 方面3.8 到 3.11 都适合这类项目太新反而容易碰到旧依赖不兼容的问题MySQL 方面用 8.0 系列就好网上搜到的 mysql 安装配置教程大多数也是基于 8.0 写的入门容易踩坑少。Python 安装时有一个关键勾选在安装向导第一页底部勾选“Add Python to PATH”。如果没勾后面在命令行里敲 python 会提示找不到命令很多新手在这里卡住。装完以后开一个命令行窗口执行下面几行命令验证环境是不是真的就绪python --version pip --version mysql --version这三条命令分别确认 Python 解释器、包管理器和 MySQL 客户端是否在系统 PATH 中。如果你在 Windows 上装了 MySQL 但 mysql 命令仍然提示 not recognized说明 MySQL Server 装了但它的 bin 目录没有加进 PATH这不影响程序通过 3306 端口连接数据库但后面导入 SQL 脚本会不方便。这种差异经常被忽略程序跑不通不一定是 Python 问题也可能是 MySQL 服务压根没启动。依赖安装用 pip 一次搞定。Flask MySQL 的课设项目最常用的组合是 Flask、PyMySQL、cryptography 三个包PyMySQL 负责让 Python 和 MySQL 对话cryptography 用于支持 MySQL 8.0 的认证插件。requirements.txt 大致长这样Flask2.2,3.0 PyMySQL1.0,2.0 cryptography39.0安装命令是pip install -r requirements.txt如果项目里用的是 mysql-connector-python 而不是 PyMySQL那连接写法会略有不同但安装思路一致。IDE 方面用 VSCode 的话python 环境配置只需要装官方 Python 扩展并在左下角选解释器用 PyCharm 的话新建项目时选 Virtualenv 环境然后在 Terminal 里执行 pip install。这些基础环境配置通常不是项目本身的坑但环境不一致会导致同一个 zip 在不同机器上表现完全不同。3.2 导入数据库脚本一条命令行和一个图形化工具都给你环境就绪后第一件正事是把 dorms.sql 导入 MySQL。这一步做对了系统才有地方读写数据。命令行方式最直接在 dorms.sql 所在目录打开终端执行mysql -u root -p dorms.sql这条命令的意思是以 root 身份连接 MySQL-p 让 MySQL 提示你输入密码然后用重定向把 SQL 文件内容作为输入交给 mysql 客户端逐条执行。如果文件内部已经写了 CREATE DATABASE IF NOT EXISTS dormitory那么数据库会自动创建如果脚本里没有建库语句你需要在执行前先手动建库否则后续的表会落到默认库下面程序连接时找不到表。图形化方式适合不习惯命令行的同学。Navicat 连接 MySQL 后右键你的连接选择“运行 SQL 文件”选中 dorms.sql 执行即可这是最快的可视化办法。MySQL Workbench 同样可以做到File → Open SQL Script 打开文件再点闪电图标执行。两种工具在导入时都有编码风险SQL 文件本身必须是 UTF-8 编码文件里如果有中文注释工具默认编码不对就会在导入阶段报错报错信息通常是 “You have an error in your SQL syntax near …”定位半天结果发现是注释乱码。导入成功后验证一下表是否存在mysql -u root -p -e USE dormitory; SHOW TABLES;这条命令用 -e 参数直接执行 SQL 而不进入交互式界面适合脚本化验证。如果能看到上一章的五六张表说明导入成功可以进入下一步。如果一张表都没有去检查 dorms.sql 开头的 CREATE DATABASE 语句是不是被工具自动截断了这是图形化导入常见的小毛病。3.3 配置文件和启动命令连不上数据库时先检查这里数据库导入成功后离跑通还差最后一步告诉代码用哪个账号、哪个密码去连 MySQL。这个信息一般集中在 config.py 里一个典型的连接配置长这样# config.py —— 数据库连接配置 DB_HOST localhost DB_PORT 3306 DB_USER root DB_PASSWORD 123456 DB_NAME dormitory SECRET_KEY dev-secret-key-set-random这些参数的含义DB_HOST 填 localhost 或 127.0.0.1指本机 MySQLDB_PORT 默认 3306除非你装 MySQL 时手工改过端口DB_NAME 要和 dorms.sql 里的建库名一致最常见的问题就是代码里写的是 dorm而脚本建的库叫 dormitory差一个单词就报 Table not found。SECRET_KEY 用于 Flask 对 session 签名课设环境随便设置一个字符串就好不用太当真。入口文件的数据库连接函数常见写法是这样# app.py —— Flask 应用入口与数据库连接 from flask import Flask, session, render_template, request, redirect import pymysql app Flask(__name__) app.config.from_pyfile(config.py) # 从 config.py 读取配置 app.secret_key app.config[SECRET_KEY] def get_db(): 每次请求创建一个数据库连接用 DictCursor 便于按字段名取值 conn pymysql.connect( hostapp.config[DB_HOST], portapp.config[DB_PORT], userapp.config[DB_USER], passwordapp.config[DB_PASSWORD], databaseapp.config[DB_NAME], charsetutf8mb4, cursorclasspymysql.cursors.DictCursor ) return conn app.route(/) def index(): return render_template(index.html) if __name__ __main__: app.run(host127.0.0.1, port5000, debugTrue)这里面有几个参数值得说明。charset 必须写 utf8mb4如果写 utf8 或干脆不写插入中文时大概率乱码这是中文场景最常见的数据库坑。cursorclass 设置成 DictCursor 后查询返回的行是字典cur.fetchone() 返回类似 {id: 1, name: 张伟} 的结构模板里可以直接按字段名取值比默认的元组方式可读性高很多。最后启动服务一条命令python app.py终端出现 “Running on http://127.0.0.1:5000” 就说明 Flask 已经在工作了浏览器打开 http://127.0.0.1:5000 能看到页面就代表整条链路已经通了一半。debugTrue 这个参数的作用是改代码后自动重启服务而且浏览器访问出错时直接显示红色报错页面方便调试但答辩演示时最好关掉否则异常堆栈会直接暴露给评委而且 debug 模式的安全性并不适合开放访问。4. 核心功能拆解登录鉴权、宿舍分配与统计报表的代码怎么写4.1 登录与角色鉴权session 怎么区分管理员、宿管和学生整套系统里最核心、也最容易被答辩追问的模块就是登录鉴权。宿舍管理系统通常有三种角色管理员、宿管员、学生三者能访问的页面和操作权限完全不同。用一个全局变量存登录用户是课设里最常见的反面教材——多几个浏览器窗口互相踢下线答辩现场一演示就露馅。用 session 才是正路Flask 的 session 基于 Cookie 存储每个浏览器维护自己的会话状态互不干扰。登录接口的常见写法from werkzeug.security import check_password_hash app.route(/login, methods[POST]) def login(): username request.form.get(username) password request.form.get(password) conn get_db() with conn.cursor() as cur: cur.execute( SELECT id, role FROM user WHERE username %s AND password %s, (username, password) ) row cur.fetchone() conn.close() if row: session[uid] row[id] session[role] row[role] return redirect(/index) return render_template(login.html, error账号或密码错误)这里有一个技术上必须讲清楚的点SQL 用了 %s 占位符而不是直接拼接字符串。直接拼 username 进去当然也能查但当你输入一个像 OR 11的账号时SQL 就变成了 always true 的查询这就是 SQL 注入。用占位符方式传参让 PyMySQL 帮你转义是从课设阶段就该养成的习惯答辩时提到这一点非常加分。拿到 role 之后每个视图函数都需要判断角色。我一般会把权限校验抽成一个装饰器避免每个接口重复写三行 if 判断from functools import wraps def role_required(roles): roles 是允许访问的角色列表比如 [admin, manager] def decorator(fn): wraps(fn) def wrapper(*args, **kwargs): if session.get(role) not in roles: return redirect(/login) return fn(*args, **kwargs) return wrapper return decorator app.route(/student/list) role_required([admin, manager]) def student_list(): # 只有管理员和宿管能看到学生列表 return render_template(student_list.html)装饰器的作用是在真正执行视图函数之前先检查 session 里的角色不在允许列表里就直接重定向到登录页。这样新加一个页面时只要在函数上方放一行role_required(...)权限判断就自动接上了。注意 session 默认是明文存储在 Cookie 里的所以生产环境必须改 SECRET_KEY但课设环境用默认值也无大碍。4.2 宿舍分配与调宿事务保证一个床位不会被分给两个人宿舍分配是第二个答辩必问点。刚看到需求时很多人的第一反应是查一下 dorm 表里的 capacity再数一下当前住了多少人小于容量就插入新记录。逻辑没错但少了两个关键步骤事务和行锁。先看一份能跑通的分配函数是什么样def allocate_room(student_id, dorm_id): 分配宿舍检查容量并在一个事务里写入住宿记录 conn get_db() try: with conn.cursor() as cur: # 锁住宿舍行避免并发时两个请求同时看到空床 cur.execute( SELECT capacity FROM dorm WHERE id %s FOR UPDATE, (dorm_id,) ) capacity cur.fetchone()[capacity] # 统计当前在住人数check_out_date 为空才是在住 cur.execute( SELECT COUNT(*) AS cnt FROM occupancy WHERE dorm_id %s AND check_out_date IS NULL, (dorm_id,) ) used cur.fetchone()[cnt] if used capacity: conn.rollback() return False, 该宿舍床位已满 cur.execute( INSERT INTO occupancy (student_id, dorm_id, check_in_date) VALUES (%s, %s, NOW()), (student_id, dorm_id) ) conn.commit() return True, 分配成功 except Exception as e: conn.rollback() return False, f分配失败{e} finally: conn.close()这段代码的核心理念是“先锁后查再写”。SELECT ... FOR UPDATE 会把这间宿舍对应的行锁住直到事务提交或回滚这样两个会话同时给同一间宿舍分人时第二个查询会等待第一个提交完才执行避免超员。事务的作用更大如果中间任何一步出错conn.rollback() 会把前面所有操作撤销数据库不会留下只有半个分配动作的脏数据。调宿的思路就是在同一个事务里做两件事把旧住宿记录的 check_out_date 更新为今天的日期再为同一名学生插入一条新入住记录。两件事要么同时成功要么同时失败否则会出现学生同时住两间宿舍的中间状态。这个业务逻辑很适合在答辩时演示先用两行 SQL 说明“为什么要事务”再展示代码里的 commit 和 rollback 对应哪一步回滚。4.3 统计报表用一条聚合 SQL 算出各楼空床位与入住率宿舍管理系统如果没有统计报表会被评委认为只是一个带界面的增删改查。常见的统计需求是每个楼栋住了多少人、还有多少空床、哪栋楼入住率最高。这类需求用一条 GROUP BY 语句就能完成关键是掌握 LEFT JOIN 和条件连接。SELECT d.building, SUM(d.capacity) AS total_beds, COUNT(o.id) AS occupied_beds, SUM(d.capacity) - COUNT(o.id) AS empty_beds, ROUND(COUNT(o.id) / SUM(d.capacity) * 100, 1) AS usage_rate FROM dorm d LEFT JOIN occupancy o ON d.id o.dorm_id AND o.check_out_date IS NULL -- 只统计在住记录 GROUP BY d.building ORDER BY usage_rate DESC, empty_beds ASC;这段 SQL 有三个细节需要理解。第一JOIN 条件是 ON 后面同时放关联字段和过滤条件即o.check_out_date IS NULL写在 ON 而不是 WHERE 里这样才能保证 LEFT JOIN 后 dorm 表左边的数据不丢如果把过滤条件放到 WHERE一个从未有人入住的宿舍楼会被整行过滤掉。第二COUNT(o.id) 统计的是右侧表非空的行数也就是实际住宿记录数而 SUM(d.capacity) 是房间的床位总和两者相减就是空床数。第三ORDER BY 可以对着聚合后的别名排序usage_rate 倒序排能直观看到哪个楼住得最满。这套统计视图非常适合做成一个独立页面展示楼栋维度、楼层维度甚至宿舍维度的下钻。答辩时从各楼入住率讲到学生居住分布比单纯讲登录分配有说服力得多。数据量不大时这种 SQL 直接跑就行如果以后数据涨到几万条可以考虑加一个统计表定时汇总不过这已经超出课设范围了。5. 避坑清单从数据库连不上到演示现场死机的五个真实问题5.1 error 2002 (HY000)MySQL 服务根本没起来现象程序里报pymysql.err.OperationalError: (2002, Cant connect to local MySQL server through socket /tmp/mysql.sock)或者 Windows 下报(10061)但 Navicat 里也连不上。原因这个报错 90% 的情况是 MySQL Server 服务没有启动不是密码错误也不是端口错误。Linux 下是 service 没起Windows 下是服务没有运行程序尝试连接 3306 端口结果没有人监听自然握手失败。解决Linux 执行systemctl status mysqld确认状态没起来就systemctl start mysqldWindows 打开服务管理器找到 MySQL80 服务右键启动并把启动类型改为自动。启动后重新跑mysql -u root -p -e SELECT 1能返回结果就说明服务正常再把报错从程序端排除。这个坑之所以排第一是因为很多人都以为代码问题反复改配置结果只是忘了点那个服务启动按钮。5.2 页面中文全部变成问号字符集从库到连接层层设现象登录页面、学生姓名、公告标题在浏览器里全部显示成????或者插入数据库的数据变成乱码但用 Navicat 直接查是能正常显示的。原因字符集在多个环节传递任何一环断了都会乱。MySQL 8.0 默认字符集是 utf8mb4但如果你建库时手动指定了 DEFAULT CHARSETutf8或者连接参数没写 charsetutf8mb4再或者 dorms.sql 文件本身是 GBK 编码被工具导入时转坏了中间环节的转换链就会断。解决按三层排查。第一层看建库语句执行SHOW CREATE DATABASE dormitory确认 DEFAULT CHARACTER SET 是 utf8mb4不是就执行ALTER DATABASE dormitory CHARACTER SET utf8mb4第二层检查连接参数config 里必须写charsetutf8mb4第三层检查 SQL 文件编码用编辑器另存为 UTF-8 无 BOM 格式再重新导入。三层全部对齐后把之前乱码的数据 DELETE 掉重建乱码问题基本绝迹。5.3 MySQL 8.0 的 caching_sha2_password命令行能连但程序连不上现象Navicat 连 MySQL 正常命令行 mysql 也能查询但 Flask 程序启动时报RuntimeError: caching_sha2_password ...或者Authentication plugin caching_sha2_password cannot be loaded。原因MySQL 8.0 默认的认证插件从 mysql_native_password 换成了 caching_sha2_passwordPyMySQL 1.0 之前的旧版本不认识这个插件于是握手失败。这不是账号密码的问题而是认证握手协议不兼容。解决两个方案选一个。升级 PyMySQL 到 1.1 以上并安装 cryptography 库让客户端支持新插件或者把用户的认证方式改回旧模式执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;。我建议用前一个方案保持 MySQL 8.0 默认配置不动因为答辩时换一台机器演示你控制不了对方 MySQL 的初始设置代码层面兼容新插件才是稳妥的做法。5.4 端口 5000 被占用或刷新后 404开发服务器的小脾气现象第一次运行python app.py失败终端提示端口已被占用或者服务器明明起来了但访问某个链接时 404其他页面正常。原因Flask 开发服务器默认监听 5000 端口如果本机已经有别的服务占用了这个端口启动必然失败。404 的情况则通常是路由注册不全或者前端链接写死了一个后端没有定义的 URL——这种问题多发生在“前端模板是现成的后端路由是自己写的”这类拼装项目里。解决启动失败时换一个端口运行改 app.run 里的 port 参数即可比如port5001但要注意页面顶部导航里的跳转链接要跟着改否则端口变了局部链接还会指向 5000。404 排错先用浏览器开发者工具看请求的完整路径再到 app.py 里搜索对应的 app.route 是否存在通常能找到拼写差异。这类问题本身不难但很磨人尤其答辩前几分钟遇到最容易心态崩溃所以演示前一定要把整个流程提前走一遍不要用“应该能跑”替代实测。5.5 答辩现场没有数据可点空列表页面暴露了功能的完整性现象演示时点开学生列表页面一片空白点报修管理没有任何记录想展示统计报表的柱状图页面上只有几行 0。评委脸上写满“这就是个空架子”。原因项目数据库导入时只有表结构没有预置业务数据或者预置数据只够登录测试。你实际演示时每一步操作都需要现场造数占用了大量答辩时间核心流程反而没时间讲。解决在导入 dorms.sql 之后再执行一份 demo_data.sql里面预置 3 栋宿舍楼、每栋 3 层、每层若干房间、60 到 80 个学生、一份代数据另外把报修单、公告也各放十几条。这样打开任何页面都有内容可讲分配宿舍时也能展示“房间已满”“调宿成功”等有对照的场景。预置数据的另一个好处是统计页面的图表立刻有形不用等现场积累数据。这个经验是很多人付过学费的答辩前夜记得做这件事。6. 答辩前的一键演示数据重置脚本让系统随时回到能看的状态前面提到预置数据很重要但只有预置还不够。答辩演示最大的风险不是功能不存在而是演示到一半把数据弄乱了分配宿舍时插错记录、调宿时点了两次、删数据时手抖——现场越紧张越容易出错。所以我会在项目里放一个 reset_demo.py 脚本专门负责把数据库恢复到预设的演示状态。这个脚本的思路很简单连接数据库清空 occupancy、repair 等业务表再重新插入一份固定的演示数据。关键点是脚本要幂等也就是无论跑多少次结果都一样不会出现重复插入。# reset_demo.py —— 重置演示数据到初始状态 import pymysql conn pymysql.connect( hostlocalhost, port3306, userroot, password123456, databasedormitory, charsetutf8mb4, autocommitFalse ) try: with conn.cursor() as cur: # 按外键依赖顺序清空业务表 cur.execute(DELETE FROM occupancy) cur.execute(DELETE FROM repair) cur.execute(DELETE FROM student) # 插入标准演示学生id 固定从 1 开始 demo_students [ (2023001, 张伟, 男, 计算机, 计科2301, 13800000001), (2023002, 李娜, 女, 软件工程, 软工2302, 13800000002), # 可以把 dorms.sql 里的预置学生在这里补全 ] cur.execute( INSERT INTO student (student_no, name, gender, major, class_name, phone) VALUES (%s, %s, %s, %s, %s, %s), demo_students ) # 为每个学生分配固定宿舍保证演示可预期 cur.execute( INSERT INTO occupancy (student_id, dorm_id, check_in_date) SELECT s.id, d.id, NOW() FROM student s, dorm d WHERE d.room_no 101 ) conn.commit() print(演示数据已重置) except Exception as e: conn.rollback() print(重置失败, e)这里有一个值得说明的顺序清空表的顺序必须遵守外键依赖关系先清 occupancy 再清 student否则外键约束会直接报错。插入学生后用一条 INSERT ... SELECT 完成“给每个学生分到 101 房间”的操作省去在代码里循环逐条插入利用 SQL 语法把两个表的关联关系一次性表达清楚这也是答辩时可以讲的点你考虑了外键约束、批量操作和脚本的幂等性。我的习惯是答辩前一晚把整条流程过一遍包括重启 MySQL、运行 reset_demo.py、浏览器从头登录到查询统计全套走完确认没有红色报错才收工。调试代码时可以写一句“理论上没问题”但演示这种事只有实测过的才叫有把握。希望这整套从选型、跑通到排错的路径能帮到你做课设时少熬几个夜。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑