Python宾馆管理系统:房态流转与入住闭环实现

发布时间:2026/9/15 17:47:11
Python宾馆管理系统:房态流转与入住闭环实现
简介这是一套面向高校计算机专业本科生的Python毕业设计与课程设计实践资源聚焦宾馆管理系统的全栈开发帮助学习者系统掌握Django Web开发核心流程。资源包含734个文件总大小18.22MB涵盖40个Python后端逻辑文件、33个HTML模板页、164个JS交互脚本、162个SVG图标资源、53个CSS样式文件及43个Vue组件含多个.bak备份文件体现前后端分离雏形与完整MVT架构落地另有SQL数据库脚本、BAT一键运行/安装批处理、LW论文与PPT演示材料构成“代码文档部署”闭环。目前已有59人学习下载适合零基础入门Django的学生通过真实业务场景会员管理、客房预约、库存事务控制、权限认证等理解模型设计、视图路由、模板渲染及并发安全机制同时可直接复用项目结构开展二次开发或答辩展示。1. 用 Python 写宾馆管理系统不是堆功能而是把「房态流转」和「入住闭环」跑通很多计算机专业学生拿到“宾馆管理系统”毕业设计选题时第一反应是不就是增删改查套个 Django 模板、连个 SQLite填满 CRUD 就交差。但实际答辩现场被问倒的往往不是不会写models.py而是说不清“为什么退房后房间状态必须从‘已入住’变成‘待清扫’而不是直接变‘空闲’”——这个细节背后是业务规则建模能力不是语法熟练度。本项目标题里带的.zip和 “LW”论文二字恰恰说明它面向的是需要交付可运行系统 可答辩逻辑链的本科实践场景。它不追求高并发或微服务架构但必须让“预订→入住→续住→退房→清洁→再预订”这条主链在本地环境稳定走通所有状态变更有日志、有回溯、有数据库约束支撑。适合 Python 初学但已掌握基础语法、能写函数和类、了解 SQLite 或 MySQL 基础操作的学生目标不是写出工业级系统而是用最小可行代码验证自己对业务流程的理解是否闭环。2. 用 Flask SQLite 实现最小可运行核心5 个模型 3 个关键状态机2.1 为什么选 Flask 而非 Django——毕业设计场景下的轻量级合理性Django 自带 Admin、ORM 强大、适合快速搭建后台但它默认包含用户权限、会话管理、中间件等毕业设计中极少用到的模块反而增加理解负担和部署复杂度。Flask 是一个 WSGI 微框架核心只处理路由和请求响应其余如数据库操作、表单验证、模板渲染全部按需引入。对毕业设计而言这意味着学生能清晰看到每个 HTTP 请求对应哪段 Python 逻辑数据库模型定义models.py与视图函数views.py解耦明确便于答辩时讲解数据流向本地调试只需flask run无需配置settings.py、manage.py等多层文件打包发布时仅需requirements.txtapp.pyinstance/目录.zip解压即跑。提示本方案使用 Flask-SQLAlchemy 作为 ORM而非原生 sqlite3 模块。原因在于 SQLAlchemy 提供声明式模型定义、关系映射、查询构造器比手写 SQL 字符串更易维护且与毕业论文中“系统采用 ORM 技术实现数据持久化”的表述完全匹配。2.2 核心模型设计紧扣“房态”与“入住”两条主线宾馆业务本质是资源房间与时间入住周期的绑定。因此模型必须围绕Room房间、Guest客人、Reservation预订、CheckInRecord入住记录、CleaningLog清洁日志五张表构建其中三张表构成状态流转主干# models.py from flask_sqlalchemy import SQLAlchemy from datetime import datetime db SQLAlchemy() class Room(db.Model): __tablename__ rooms id db.Column(db.Integer, primary_keyTrue) room_number db.Column(db.String(10), uniqueTrue, nullableFalse) # 如 A101 room_type db.Column(db.String(20), nullableFalse) # 标准间/豪华套间 status db.Column(db.String(15), defaultvacant) # vacant/occupied/cleaning/maintenance price_per_night db.Column(db.Float, nullableFalse) class Guest(db.Model): __tablename__ guests id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(50), nullableFalse) id_card db.Column(db.String(18), uniqueTrue, nullableFalse) # 身份证号 phone db.Column(db.String(15)) class CheckInRecord(db.Model): __tablename__ check_in_records id db.Column(db.Integer, primary_keyTrue) guest_id db.Column(db.Integer, db.ForeignKey(guests.id), nullableFalse) room_id db.Column(db.Integer, db.ForeignKey(rooms.id), nullableFalse) check_in_time db.Column(db.DateTime, defaultdatetime.now) expected_check_out db.Column(db.DateTime, nullableFalse) actual_check_out db.Column(db.DateTime, nullableTrue) status db.Column(db.String(15), defaultchecked_in) # checked_in/checked_out/extended2.2.1 房间状态机5 种状态及其触发条件状态触发动作数据库约束vacant空闲新建房间、清洁完成statusvacant AND actual_check_out IS NOT NULLoccupied已入住办理入住statusoccupied AND actual_check_out IS NULLcleaning待清扫退房后自动触发外键关联CleaningLog表room_id必须存在maintenance维修中手动设置需填写维修原因maintenance_reason字段非空reserved已预订预订成功但未入住Reservation表中statusconfirmed且无对应CheckInRecord注意Room.status不应由前端直接修改而必须通过业务方法调用。例如room.check_in(guest)方法内部校验room.status vacant后才更新状态并创建CheckInRecord避免状态跳跃如从vacant直接跳到checked_out。2.3 初始化数据库与插入测试数据3 行命令搞定本地验证毕业设计最怕“代码写完却跑不起来”。以下命令在项目根目录执行确保 SQLite 文件生成、表结构创建、基础测试数据就位# 1. 安装依赖假设已安装 pip pip install flask flask-sqlalchemy # 2. 设置环境变量Windows 下用 setmacOS/Linux 用 export export FLASK_APPapp.py export FLASK_ENVdevelopment # 3. 初始化数据库并填充示例数据 flask init-db对应app.py中需定义init-db命令# app.py from flask import Flask from models import db app Flask(__name__) app.config[SQLALCHEMY_DATABASE_URI] sqlite:///instance/hotel.db app.config[SQLALCHEMY_TRACK_MODIFICATIONS] False db.init_app(app) app.cli.command() def init_db(): 初始化数据库创建表 插入测试房间和客人 db.create_all() # 插入 3 间测试房间 from models import Room, Guest if Room.query.count() 0: for num, rtype in [(A101, 标准间), (B202, 豪华套间), (C303, 家庭房)]: db.session.add(Room(room_numbernum, room_typertype, price_per_night280.0)) if Guest.query.count() 0: db.session.add(Guest(name张三, id_card11010119900307271X, phone13800138000)) db.session.commit() print(✅ 数据库初始化完成3 间房间 1 位测试客人)执行flask init-db后项目目录下会生成instance/hotel.db文件可用 DB Browser for SQLite 打开验证表结构与数据。这步是后续所有功能开发的前提也是答辩时演示“系统能跑起来”的第一证据。3. 实现入住与退房闭环状态变更 时间校验 日志留痕3.1 入住逻辑从“空闲”到“已入住”的原子操作入住不是简单地把Room.status改成occupied而是一组关联操作的集合检查房间是否空闲 → 创建入住记录 → 更新房间状态 → 记录操作时间。关键在于事务一致性——任一环节失败整个操作应回滚。# services/check_in_service.py from datetime import timedelta from models import db, Room, Guest, CheckInRecord def perform_check_in(room_number: str, guest_id: int, days: int 1) - dict: 办理入住返回结果字典含 success、message、record_id :param room_number: 房间号如 A101 :param guest_id: 客人ID :param days: 预计入住天数默认1天 try: room Room.query.filter_by(room_numberroom_number).first() if not room: return {success: False, message: f房间 {room_number} 不存在} if room.status ! vacant: return {success: False, message: f房间 {room_number} 当前状态为 {room.status}不可入住} guest Guest.query.get(guest_id) if not guest: return {success: False, message: 客人信息不存在} # 计算预计退房时间当前时间 days 天 expected_checkout datetime.now() timedelta(daysdays) # 创建入住记录 record CheckInRecord( guest_idguest_id, room_idroom.id, expected_check_outexpected_checkout ) db.session.add(record) db.session.flush() # 获取 record.id但不提交 # 更新房间状态 room.status occupied # 提交事务 db.session.commit() return { success: True, message: f入住成功房间 {room_number} 已占用预计 {expected_checkout.strftime(%Y-%m-%d %H:%M)} 退房, record_id: record.id } except Exception as e: db.session.rollback() return {success: False, message: f入住失败{str(e)}}3.1.1 关键参数说明与可调项参数类型说明毕业设计可调整点room_numberstr房间唯一标识用于 UI 输入框绑定可改为room_id整数减少字符串查询开销guest_idint客人主键避免身份证号明文传递若需支持新客人注册此处应调用create_guest()daysint预计入住天数决定expected_check_out可扩展为接收check_out_date字符串用datetime.strptime()解析提示db.session.flush()在commit()前获取自增主键 ID是 Flask-SQLAlchemy 中常用技巧。若直接commit()后再取record.id则无法在同事务内做后续关联操作如记录日志。3.2 退房逻辑状态回滚 清洁任务生成 费用计算雏形退房是状态机中最复杂的环节需校验当前是否为occupied状态 → 更新actual_check_out→ 将房间设为cleaning→ 生成清洁任务 → 计算实际费用可选。以下代码聚焦状态与日志费用部分留作扩展点# services/check_out_service.py from datetime import datetime from models import db, Room, CheckInRecord, CleaningLog def perform_check_out(record_id: int) - dict: 办理退房更新入住记录、房间状态并生成清洁日志 :param record_id: 入住记录ID try: record CheckInRecord.query.get(record_id) if not record: return {success: False, message: 未找到该入住记录} if record.status ! checked_in: return {success: False, message: 该记录状态异常无法退房} # 校验房间当前状态 room Room.query.get(record.room_id) if room.status ! occupied: return {success: False, message: f房间 {room.room_number} 状态异常{room.status}} # 更新入住记录 record.actual_check_out datetime.now() record.status checked_out # 更新房间状态为 cleaning room.status cleaning # 生成清洁日志异步任务可在此处加 Celery毕业设计用同步即可 cleaning_log CleaningLog( room_idroom.id, assigned_to保洁员A, scheduled_timedatetime.now(), statuspending ) db.session.add(cleaning_log) db.session.commit() return { success: True, message: f退房成功房间 {room.room_number} 进入待清扫状态清洁任务已生成, cleaning_log_id: cleaning_log.id } except Exception as e: db.session.rollback() return {success: False, message: f退房失败{str(e)}}3.2.1 清洁日志表结构与毕业设计价值# models.py 新增 class CleaningLog(db.Model): __tablename__ cleaning_logs id db.Column(db.Integer, primary_keyTrue) room_id db.Column(db.Integer, db.ForeignKey(rooms.id), nullableFalse) assigned_to db.Column(db.String(30), nullableFalse) # 分配给谁 scheduled_time db.Column(db.DateTime, nullableFalse) # 计划清洁时间 completed_time db.Column(db.DateTime, nullableTrue) # 实际完成时间 status db.Column(db.String(15), defaultpending) # pending/completed/failed notes db.Column(db.Text) # 清洁备注如“地毯污渍需特殊处理”此表的存在使系统具备了业务可追溯性答辩时可展示“某房间退房后自动生成清洁任务”证明系统不只是 CRUD而是模拟真实运营流程。同时status字段为后续扩展如清洁完成确认预留接口。3.3 Web 路由与简易前端用纯 HTML Jinja2 实现可操作界面毕业设计不需要 React/VueFlask 自带的 Jinja2 模板引擎足够支撑基础交互。以下为入住页面路由示例# app.py from flask import render_template, request, redirect, url_for from services.check_in_service import perform_check_in app.route(/check-in, methods[GET, POST]) def check_in_view(): if request.method POST: room_num request.form[room_number] guest_id int(request.form[guest_id]) days int(request.form.get(days, 1)) result perform_check_in(room_num, guest_id, days) return render_template(result.html, resultresult) # GET 请求显示入住表单 guests Guest.query.all() rooms Room.query.filter_by(statusvacant).all() # 只显示空闲房间 return render_template(check_in.html, guestsguests, roomsrooms)对应templates/check_in.html!-- templates/check_in.html -- h2办理入住/h2 form methodPOST label选择房间select nameroom_number required {% for r in rooms %} option value{{ r.room_number }}{{ r.room_number }} ({{ r.room_type }})/option {% endfor %} /select/labelbrbr label选择客人select nameguest_id required {% for g in guests %} option value{{ g.id }}{{ g.name }} ({{ g.id_card[:6] }}****{{ g.id_card[-4:] }})/option {% endfor %} /select/labelbrbr label入住天数input typenumber namedays value1 min1 max30/labelbrbr button typesubmit确认入住/button /form注意room_number下拉框只显示statusvacant的房间这是前端层面的状态过滤与后端perform_check_in()中的校验形成双重保险。答辩时可强调“前后端协同校验保障业务规则不被绕过”。4. 毕业设计论文LW关键图表与 ER 图绘制实操指南4.1 ER 图必须体现“状态驱动”而非“纯实体关系”很多学生画 ER 图时只连接Room–Guest–Reservation三个矩形用菱形标“入住”关系这属于教科书式画法无法体现本系统的核心——状态变迁。正确做法是将status字段提升为独立实体并标注其取值范围与转换条件------------ ---------------- ------------ | Room | | CheckInRecord | | Guest | |------------| |----------------| |------------| | id |-----| id |-----| id | | room_number| | guest_id | | name | | room_type | | room_id | | id_card | | status | | check_in_time | | phone | | price... | | expected... | ------------ ------------ | actual... | | status | ---------------- ▲ | 状态值枚举 | ------------------------- | status 取值及含义 | ------------------------- | checked_in | | checked_out | | extended | -------------------------4.1.1 用 draw.io 绘制可编辑 ER 图的 3 步操作访问 https://draw.io免费在线工具新建空白图表左侧工具栏选择Entity Relation分类拖入Entity矩形和Relationship菱形右键实体 →Edit Style→ 在text字段手动输入字段列表如Room\nid\nroom_number\nstatus用\n换行关系菱形中输入“入住”并用正交连线连接三方。提示答辩 PPT 中的 ER 图建议导出为 PNG但源文件.drawio必须随.zip一起提交证明图表为原创绘制非截图盗用。4.2 数据库表结构 SQL 导出答辩材料中的硬证据毕业设计论文“数据库设计”章节不能只贴文字描述必须附上可执行的建表语句。Flask-SQLAlchemy 可通过db.create_all()生成表但要导出 SQL需借助sqlacodegen工具反向生成# 安装反向工程工具 pip install sqlacodegen # 从 SQLite 数据库生成 models.py含完整表结构 sqlacodegen sqlite:///instance/hotel.db models_generated.py生成的models_generated.py中包含类似以下内容可直接复制到论文“附录 A 数据库建表语句”中CREATE TABLE rooms ( id INTEGER NOT NULL PRIMARY KEY, room_number VARCHAR(10) NOT NULL UNIQUE, room_type VARCHAR(20) NOT NULL, status VARCHAR(15) DEFAULT vacant, price_per_night FLOAT NOT NULL ); CREATE TABLE guests ( id INTEGER NOT NULL PRIMARY KEY, name VARCHAR(50) NOT NULL, id_card VARCHAR(18) NOT NULL UNIQUE, phone VARCHAR(15) );4.2.1 表字段注释规范让评审老师一眼看懂设计意图在论文表格中每张表应以 Markdown 表格形式呈现并为关键字段添加业务注释字段名类型是否为空注释statusVARCHAR(15)NOT NULL房间当前状态取值vacant/occupied/cleaning/maintenance/reserved驱动业务流程actual_check_outDATETIMENULL退房实际时间为空表示尚未退房用于计算实时房态scheduled_timeDATETIMENOT NULL清洁任务计划开始时间支持按优先级调度此表格比单纯列字段更有说服力体现学生对业务语义的理解深度。4.3 系统演示视频脚本3 分钟讲清“为什么这个设计能过答辩”毕业设计答辩常限时 5 分钟其中 3 分钟留给系统演示。脚本必须聚焦“状态流转”这一主线避免陷入代码细节开场0:00–0:30打开浏览器进入首页展示“空闲房间列表”3 间强调“此时所有房间statusvacant”入住演示0:30–1:20选择房间 A101、客人张三、入住 2 天 → 点击“确认入住” → 页面提示成功 → 刷新房间列表A101 状态变为occupied并显示“预计 2 天后退房”退房演示1:20–2:10进入“入住中记录”页找到 A101 记录 → 点击“退房” → 提示成功 → 查看房间列表A101 变为cleaning同时“清洁任务”页出现新条目收尾2:10–3:00打开数据库文件DB Browser定位rooms表指出status字段值变化再打开cleaning_logs表说明“系统自动触发下游任务体现业务闭环”。注意演示全程不敲代码、不进终端所有操作在浏览器完成。答辩老师关注的是“你是否理解业务”而非“你能否背出 Flask 路由写法”。5. 源码打包与答辩材料清单确保 .zip 里每一项都经得起提问5.1 标准化项目目录结构让评审老师 3 秒定位关键文件毕业设计.zip文件解压后目录结构必须清晰、命名规范杜绝“新建文件夹”“未命名文件”等混乱命名。标准结构如下hotel_system/ ├── app.py # 主程序入口含 Flask 初始化与路由 ├── models.py # 所有数据库模型定义 ├── services/ # 业务逻辑封装check_in_service.py, check_out_service.py ├── templates/ # Jinja2 模板base.html, check_in.html, result.html ├── static/ # CSS/JS可选简单样式用内联 style 即可 ├── instance/ # SQLite 数据库文件存放目录.gitignore 中已排除 │ └── hotel.db ├── requirements.txt # 依赖清单flask2.3.3, flask-sqlalchemy3.0.5 ├── README.md # 10 行说明如何运行、默认账号密码、测试数据说明 └── LW/ # 论文相关材料 ├── hotel_design.pdf # 毕业论文 PDF含 ER 图、数据库设计、系统截图 └── figures/ # ER 图源文件.drawio、系统界面截图PNG5.1.1requirements.txt必须锁定版本号很多学生只写flask导致评审老师用新版 Flask如 3.x运行时报错。正确写法是# requirements.txt Flask2.3.3 Flask-SQLAlchemy3.0.5 click8.1.7 itsdangerous2.1.2 Jinja23.1.2 MarkupSafe2.1.3 Werkzeug2.3.7获取方式在开发环境执行pip freeze requirements.txt然后手动删去无关包如pip、setuptools。5.2README.md写作模板直击评审老师最可能问的 3 个问题# 宾馆管理系统Python 毕业设计 ## ✅ 如何运行 1. 安装 Python 3.8 2. pip install -r requirements.txt 3. export FLASK_APPapp.py export FLASK_ENVdevelopmentWindows 用 set 4. flask init-db 初始化数据库 5. flask run 启动服务访问 http://127.0.0.1:5000 ## 默认测试数据 - 房间A101标准间、B202豪华套间、C303家庭房 - 客人张三身份证 11010119900307271X - 所有操作无需登录直接使用 ## ❓ 常见问题 Q为什么退房后房间状态是 cleaning 而不是 vacant A模拟真实酒店流程——退房后需保洁员清扫消毒完成后才可重新出租此状态确保资源不被误分配。 Q系统支持多人同时入住同一房间吗 A当前设计为“一房一入住记录”如需家庭入住可在 CheckInRecord 中增加 occupancy_count 字段并修改校验逻辑。 Q数据库用 SQLite能换成 MySQL 吗 A可以。只需修改 app.py 中 SQLALCHEMY_DATABASE_URI 为 mysqlpymysql://user:passlocalhost/dbname并安装 pymysql。提示README.md是评审老师打开.zip后看到的第一个文件它决定了对项目的第一印象。务必用 ✅//❓ 符号引导视线用短句回答高频问题避免长段落。5.3 论文LW中“系统测试”章节的实操写法不要写“经过测试系统运行稳定”而要给出可复现的测试用例表格测试编号测试项输入预期输出实际结果是否通过TC-01空闲房间入住房间 A101客人张三2 天入住成功A101 状态变occupied✅是TC-02已入住房间重复入住房间 A101当前occupied提示“房间状态异常不可入住”✅是TC-03退房触发清洁任务对 A101 入住记录执行退房cleaning_logs表新增 1 条记录✅是每条用例对应一次真实操作截图存于LW/figures/截图需包含浏览器地址栏、操作按钮、结果提示三要素。这种写法比“黑盒测试”“白盒测试”等术语堆砌更有说服力。最后把hotel_system/目录压缩为宾馆管理系统源码python毕业设计完整源代码LW.zip确保解压后顶层是hotel_system文件夹而非一堆零散文件。本文还有配套的精品资源点击获取