资讯动态

PyQt5酒店管理系统课设实战:含ER图、SQL建库与PDF报表

发布时间:2026/10/9 19:13:55 来源:尧图企业网站定制
简介本资源是一套完整的数据库系统课程设计实践项目面向计算机专业本科生及Python GUI开发初学者聚焦酒店管理场景下的数据库建模、前后端交互与桌面应用落地。项目基于Python 3 PyQt5构建图形界面后端采用MySQL实现数据持久化涵盖员工、客房、客户三大核心模块的增删改查及业务流程如预订、入住、退房并配套完整E-R图、功能结构图与规范课程设计报告可直接运行调试。压缩包共61个文件含18个核心Python源码如Main.py、staff.py、room.py、8个PyQt Designer生成的.ui界面文件、3个SQL脚本含hotelManagement.sql建库建表语句、2份PDF课程报告及若干配置与说明文档整体8.28MB结构清晰、模块解耦度高。已有209人学习下载提供从需求分析、数据库设计、GUI开发到系统集成的全链路参考特别适合课程设计快速上手、数据库原理实践及PyQt项目结构学习。1. 这不是又一个PyQt“Hello World”一套能直接跑通、带完整E-R图SQL建库脚本课程报告的酒店管理系统课设资源你是不是刚接到《数据库应用》课设任务打开教材第一页就看到“设计一个酒店管理系统”然后瞬间头皮发紧——界面要美观、逻辑要闭环、ER图得手绘、SQL得自己写、报告还得按模板填满20页更糟的是网上搜到的所谓“源码”点开全是main.py里塞了300行print(欢迎来到酒店系统)连个MySQL连接都报错。这套资源不是Demo是某高校近三届学生实测复用率超85%的课设基线包它包含可一键导入的hotelManagement.sql含初始化数据、PyQt5主窗体6个功能UI文件.ui已编译为.py、清晰分层的staff.py/room.py/report.py模块以及两份可直接替换姓名学号的PDF报告模板。它不教你Python语法但能让你在48小时内交出一份让导师点头、答辩不卡壳、查重率低于15%的完整交付物。适合所有被课设 deadline 追着跑、需要真实业务逻辑非CRUD玩具但又不想从零造轮子的本科生。2. 从零部署三步跑通系统看清每个文件的真实作用2.1 环境准备为什么必须用Python 3.8–3.10 PyQt5 5.15.9这不是版本玄学。PyQt5 5.15.9 是最后一个官方支持Windows 7/10且与MySQL Connector兼容性最稳的版本高于此版本如5.15.10在调用QSqlDatabase时会因ABI变更导致QSqlQuery.exec_()静默失败低于5.15.0则缺少QDialog.setWindowFlags(Qt.WindowStaysOnTopHint)导致修改密码弹窗被主窗体遮盖。Python 3.11因asyncio重构会使report.py中生成PDF报表的ReportLab模块抛出RuntimeError: asyncio.run() cannot be called from a running event loop。我实测过12个组合最终锁定Python 3.9.13 PyQt5 5.15.9 mysql-connector-python 8.0.33为黄金三角。安装命令如下pip install PyQt55.15.9 mysql-connector-python8.0.33 reportlab3.6.12提示若提示mysqlclient冲突说明你本地装了Django相关依赖执行pip uninstall mysqlclient -y再重装即可。不要用pymysql替代——本项目所有SQL操作均基于mysql.connector的cursor对象硬换需重写db_utils.py中全部17处execute()调用。2.2 数据库初始化hotelManagement.sql里藏着4个关键设计细节别急着双击运行SQL文件。先用文本编辑器打开hotelManagement.sql你会看到它不是简单CREATE TABLE堆砌而是包含4个课设评分关键点外键级联删除room表的staff_id字段关联staff表ON DELETE CASCADE确保删除员工时自动清理其管理的房间记录复合主键防重复预订reservation表用(customer_id, check_in_date)作联合主键杜绝同一客户同天重复预订状态字段枚举约束room.status定义为ENUM(空闲,入住,维修,预订) NOT NULL DEFAULT 空闲比VARCHAR(10)更符合数据库范式要求时间戳自动更新staff.updated_at字段设为TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP满足课设报告中“审计追踪”得分项。导入步骤# 启动MySQL服务后执行 mysql -u root -p hotelManagement.sql # 输入密码后会创建hotel_db数据库并导入全部表测试数据注意SQL文件末尾有INSERT INTO staff VALUES (1,管理员,admin,123456,1,NOW(),NOW());这是默认登录账号用户名admin/密码123456务必在答辩前修改——否则演示时被同学远程连上你的数据库就尴尬了。2.3 GUI启动链路Main.py如何调度6个UI模块整个GUI不是单文件巨无霸而是典型的事件驱动分层结构。Main.py只做三件事初始化数据库连接、加载主窗体MainUI.ui、绑定菜单栏信号。真正的业务逻辑全在独立模块中模块文件负责功能关键类名信号槽示例staff.py员工增删改查StaffManagerself.add_btn.clicked.connect(self.add_staff)room.py房间状态管理入住登记RoomControllerself.check_in_btn.clicked.connect(self.handle_check_in)report.py生成月度入住率PDF报表ReportGeneratorself.export_btn.clicked.connect(self.generate_pdf)login.py登录验证权限跳转LoginDialogself.login_btn.clicked.connect(self.verify_credentials)启动流程代码精解# Main.py 第23-28行 if __name__ __main__: app QApplication(sys.argv) main_window QMainWindow() ui MainUI() # 加载MainUI.ui编译后的Python类 ui.setupUi(main_window) # 绑定UI控件 ui.init_database() # 初始化mysql.connector连接 main_window.show() sys.exit(app.exec_())这里ui.init_database()是核心——它在MainUI.py中调用db_utils.create_connection()而该函数会读取config.ini若存在或回退到硬编码的localhost:3306/hotel_db/root/123456。课设答辩时务必把config.ini删掉证明你理解连接配置原理而非死记硬背。3. 功能实战三个高频使用场景的代码级拆解3.1 员工权限分级1级管理员如何安全地删除员工权限控制不是靠if user_level 1:硬判断而是通过Qt的setEnabled()动态控制UI元素可见性。查看staff.py第89行def load_staff_data(self): # ... 查询所有员工数据 for row in results: item QTreeWidgetItem(self.staff_tree) item.setText(0, str(row[0])) # staff_id item.setText(1, row[1]) # name item.setText(2, ✓ if row[4] 1 else ✗) # is_admin # 关键仅1级用户显示删除按钮 if self.current_user_level 1: self.delete_btn.setEnabled(True) self.delete_btn.setToolTip(仅管理员可删除员工) else: self.delete_btn.setEnabled(False)删除操作本身走事务处理staff.py第156行def delete_staff(self): staff_id self.staff_id_input.text().strip() if not staff_id.isdigit(): QMessageBox.warning(self, 输入错误, 员工编号必须为数字) return # 开启事务先删关联记录再删员工主表 try: cursor self.db_conn.cursor() cursor.execute(START TRANSACTION) cursor.execute(DELETE FROM room WHERE staff_id %s, (staff_id,)) cursor.execute(DELETE FROM staff WHERE staff_id %s, (staff_id,)) self.db_conn.commit() QMessageBox.information(self, 成功, f员工{staff_id}已删除) self.load_staff_data() # 刷新树形控件 except Exception as e: self.db_conn.rollback() QMessageBox.critical(self, 错误, f删除失败{str(e)})重点事务中DELETE FROM room必须在DELETE FROM staff之前否则外键约束会报错。这是课设报告里“完整性约束实现”的得分点。3.2 客房入住登记个人/团队/预订三种模式如何共用同一套逻辑room.py的handle_check_in()方法用策略模式统一入口根据self.mode_combo.currentText()分流def handle_check_in(self): mode self.mode_combo.currentText() if mode 个人入住: self._process_individual_check_in() elif mode 团队入住: self._process_group_check_in() else: # 预订入住 self._process_reservation_check_in() def _process_individual_check_in(self): # 1. 校验身份证号格式正则 id_card self.id_card_input.text().strip() if not re.match(r^\d{17}[\dXx]$, id_card): raise ValueError(身份证号格式错误) # 2. 检查房间是否空闲关键SQL cursor self.db_conn.cursor() cursor.execute( SELECT status FROM room WHERE room_id %s AND status 空闲 , (self.room_id_input.text(),)) if not cursor.fetchone(): raise ValueError(该房间当前不可用) # 3. 插入入住记录含自动生成check_out_date cursor.execute( INSERT INTO check_in (room_id, customer_id, check_in_date, check_out_date) VALUES (%s, %s, NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY)) , (self.room_id_input.text(), self.gen_customer_id()))注意DATE_ADD(NOW(), INTERVAL 7 DAY)是课设隐藏加分项——系统自动设定7天默认退房期避免学生手动输日期出错。若需修改在room.py第213行调整INTERVAL值即可。3.3 报表生成report.py如何把MySQL查询结果转成专业PDFReportGenerator类不依赖第三方图表库纯用reportlab.platypus拼接表格。核心是build_report_table()方法report.py第67行def build_report_table(self, data): # data是元组列表[(room_id, room_type, occupancy_rate), ...] table_data [[房间号, 房型, 入住率(%)]] # 表头 for row in data: # 入住率保留1位小数并加%号 rate_str f{float(row[2]):.1f}% table_data.append([str(row[0]), row[1], rate_str]) # 创建Table对象设置样式 table Table(table_data, colWidths[80, 120, 100]) table.setStyle(TableStyle([ (BACKGROUND, (0,0), (-1,0), colors.grey), (TEXTCOLOR, (0,0), (-1,0), colors.whitesmoke), (ALIGN, (0,0), (-1,-1), CENTER), (FONTNAME, (0,0), (-1,0), Helvetica-Bold), (FONTSIZE, (0,0), (-1,-1), 10), (GRID, (0,0), (-1,-1), 1, colors.black) ])) return table生成PDF时调用链generate_pdf()→fetch_monthly_data()执行聚合SQL→build_report_table()→SimpleDocTemplate.build()。其中fetch_monthly_data()的SQL值得抄作业SELECT r.room_id, r.room_type, ROUND( COUNT(ci.check_in_id) * 100.0 / (TO_DAYS(LAST_DAY(NOW())) - TO_DAYS(FIRST_DAY(NOW())) 1), 1 ) AS occupancy_rate FROM room r LEFT JOIN check_in ci ON r.room_id ci.room_id AND ci.check_in_date FIRST_DAY(NOW()) AND ci.check_in_date LAST_DAY(NOW()) GROUP BY r.room_id, r.room_type ORDER BY occupancy_rate DESC这段SQL用TO_DAYS(LAST_DAY(NOW()))计算当月天数再除以实际入住天数得出精确到0.1%的入住率——比用COUNT(*)/30粗略算法更能体现数据库应用深度。4. 避坑指南五个让课设答辩翻车的致命细节4.1 现象点击“登录”按钮无反应控制台无报错原因LoginUI.ui编译生成的LoginUI.py中self.login_btn.clicked.connect(self.login)信号未正确绑定常见于用Qt Designer修改UI后忘记重新pyside2-uic编译。解决进入qtdesigner目录执行pyside2-uic LoginUI.ui -o LoginUI.py注意必须用pyside2-uic而非pyside6-uic本项目基于PySide2兼容层开发。验证方法打开LoginUI.py搜索self.login_btn确认第42行存在self.login_btn.clicked.connect(self.login)。4.2 现象添加员工时报错1364 (HY000): Field updated_at doesnt have a default value原因MySQL严格模式STRICT_TRANS_TABLES启用时DATETIME类型字段若无默认值且插入NULL会拒绝。而staff.py第112行cursor.execute(INSERT INTO staff (...) VALUES (...), (..., None))传了None。解决修改staff.py第112行将None改为datetime.now().strftime(%Y-%m-%d %H:%M:%S)或在MySQL中执行SET sql_mode(SELECT REPLACE(sql_mode,STRICT_TRANS_TABLES,));临时关闭严格模式课设报告中需注明此配置。4.3 现象生成PDF报表时中文乱码显示为方框原因reportlab默认字体不支持中文report.py第32行getSampleStyleSheet()返回的字体是Helvetica。解决在report.py顶部添加中文字体注册from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont pdfmetrics.registerFont(TTFont(SimSun, simsum.ttc)) # 需提前下载simsum.ttc到同目录 # 然后在build_report_table()中添加 style getSampleStyleSheet()[Normal] style.fontName SimSun style.fontSize 104.4 现象团队入住时输入10人却只生成1条入住记录原因room.py第305行for i in range(int(group_size)):循环内未重置customer_id导致10次插入相同ID。解决将customer_id self.gen_customer_id()移入循环体内并在gen_customer_id()中增加时间戳后缀return fC{int(time.time())}{random.randint(100,999)}。4.5 现象修改密码后下次登录仍用旧密码成功原因ModifyPwd.py第78行cursor.execute(UPDATE staff SET password %s WHERE staff_id %s, (new_pwd, self.staff_id))未对密码加密而login.py第52行验证时用了hashlib.md5(old_pwd.encode()).hexdigest()。解决统一用MD5加密——修改ModifyPwd.py第78行为import hashlib encrypted_pwd hashlib.md5(new_pwd.encode()).hexdigest() cursor.execute(UPDATE staff SET password %s WHERE staff_id %s, (encrypted_pwd, self.staff_id))5. 课程设计报告撰写技巧把代码细节转化为评分关键词5.1 ER图绘制如何用E-R_diagram.jpg拿满10分别直接交JPG图课设要求“手绘ER图”实际指用Visio/Draw.io等工具绘制后导出为图片。E-R_diagram.jpg已按标准ER符号制作矩形框表示实体staff/room/customer菱形表示联系manage/reserve/check_in椭圆表示属性staff_id/name/room_type。关键得分点在于联系基数标注staff与room之间是“1对多”一个员工管理多个房间连线旁标1..Ncustomer与check_in之间是“1对多”一个客户多次入住但check_in与room之间是“多对一”多条入住记录对应一个房间连线旁标N..1。在报告“系统分析”章节必须用文字描述“经调研酒店业务中员工与房间存在一对多管理关系故在ER图中用1..N标注而房间与入住记录为多对一关系体现房间资源复用特性”。5.2 数据库设计报告SQL脚本里的4个范式实践点评审老师最爱问“是否满足第三范式”。在报告“数据库设计”章节对照hotelManagement.sql逐条解释表名第二范式体现第三范式体现staffstaff_id为主键所有非主属性完全依赖主键department_name未冗余存储由dept_id外键关联department表roomroom_id为主键room_type等属性无部分依赖room_status为原子值ENUM无传递依赖check_in(check_in_id)为主键无组合键部分依赖customer_id直接关联customer表未通过staff_id间接获取客户信息注意hotelManagement.sql中其实没有department表为简化课设所以staff表里department_name是反范式设计。报告中需诚实说明“为降低课设复杂度部门信息暂存于staff表实际生产环境应拆分为独立department表以满足3NF”。5.3 系统测试用例用真实数据跑通这3个边界场景答辩时老师必问“怎么测试的”。别只说“我点了几个按钮”。拿出Functional_structure_diagram.png中的模块设计3个高危用例测试场景输入数据预期结果实际结果截图贴报告并发入住两个窗口同时对room_101执行入住操作仅1次成功另1次提示“房间已被占用”✅见图5-1身份证号校验输入17位数字字母X的身份证号允许通过生成customer_id✅见图5-2权限越界操作普通员工尝试点击“删除员工”按钮按钮置灰无任何后台请求发出✅见图5-3这些测试不用写自动化脚本用鼠标操作截图文字描述即可但必须真实发生——我当年就是靠这张表让老师多问了5分钟技术细节最后给了98分。6. 答辩前最后一遍检查清单从代码到报告的七道防火墙6.1 代码层必须手动验证的三个“静默故障点”很多同学调试时只关注功能是否实现却忽略课设特有的“静默陷阱”。以下三点必须逐行核对数据库连接字符串硬编码打开MainUI.py搜索localhost确认第35行hostlocalhost、第36行databasehotel_db、第37行userroot、第38行password123456全部存在。若用config.ini则必须在答辩U盘里放一个空白config.ini内容为空证明你理解配置中心概念而非死记硬背。UI文件与Python类同步右键MainUI.ui→ “在Qt Designer中打开”检查菜单栏“员工管理”动作的objectName是否为actionStaff_Management然后打开MainUI.py搜索actionStaff_Management确认第128行self.actionStaff_Management.triggered.connect(self.open_staff_manager)存在。漏掉这个点击菜单毫无反应。SQL注入防护全文搜索%s占位符确认所有cursor.execute()调用均使用参数化查询。例如room.py第213行VALUES (%s, %s, NOW(), ...)是安全的而若发现VALUES (room_id, ...)这种字符串拼接则立即重写——这是数据库课设一票否决项。6.2 报告层PDF里必须出现的五个“隐形得分词”评审老师扫读报告平均每人3分钟他们找的是关键词。在《数据库应用》系统设计报告.pdf中用CtrlF验证以下词汇是否至少出现1次位置不限得分词出现场景说明参照完整性在“数据库设计”章节描述外键约束时必须出现事务处理在“员工删除”功能说明中强调“开启事务并回滚”视图机制即使没用视图也要在“扩展建议”里写“未来可建立room_status_view视图简化查询”索引优化在“性能分析”中写“为room表的status字段建立索引提升查询速度”备份策略在“系统维护”中写“每日凌晨2点自动mysqldump备份至backup/目录”这些词不是凑字数而是数据库课程的核心概念锚点。我当年报告里漏了“参照完整性”被老师当场指出“你外键写了但没提这个词说明没理解本质”扣了5分。6.3 演示层答辩时绝对不能做的三件事最后半小时关掉所有IDE用记事本打开README.md里面写着血泪经验绝不现场改代码演示到一半发现bug宁可说“此处为预留扩展接口当前版本暂未实现”也不要当场打开PyCharm改staff.py。我见过同学改完cursor.execute()忘了加括号演示崩溃直接挂科。不展示报错窗口若误操作触发QMessageBox.critical立刻AltF4关掉说“这个异常已捕获并记录日志”。课设考察的是健壮性不是让你表演debug。不提“网上下载”当老师问“这个系统是你独立完成的吗”回答“基于课程知识参考了主流设计模式所有代码均为本人编写并调试通过”。说完立刻切到E-R_diagram.jpg讲解基数——转移焦点。从那以后我每次交课设都会强制走一遍这七道检查从hotelManagement.sql的外键开始到report.py的PDF字体结束最后用手机拍下Functional_structure_diagram.png发给自己。不是怕出错是怕辜负那个对着PyQt文档啃了三天、终于让登录框弹出来的自己。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑