本文还有配套的精品资源点击获取简介这个Python酒店管理系统用Django框架开发支持客户和管理员双角色操作包含注册登录、房间查询与预订、订单管理、押金收取、报表统计等实用功能。前端页面齐全有login.html、register.html、customerindex.html、managerindex.html、bookdetail.html、baobiao.html等10多个HTML模板配合独立的CSS、JS和图片资源交互清晰。后端代码结构规范models.py定义了用户、客房、订单等核心数据模型views.py封装业务逻辑urls.py完成路由分发settings.py配置基础参数所有模块在本地环境实测可运行。压缩包里还附带一份完整的课程报告PDF涵盖需求分析、ER图设计、数据库表结构、各功能页面测试截图及开发总结内容详实、注释充分适合软件工程或Web开发课程期末作业使用也适合作为Django入门实践参考。1. 项目概述为什么这个Django酒店系统值得你花两小时认真看一遍我带过六届软件工程课的课程设计每年都会收到上百份“学生版酒店管理系统”——其中八成是直接从GitHub抄来的半成品登录页能跑预订功能点进去就500三成连数据库迁移都没做全python manage.py migrate一执行就报错剩下不到一成勉强能跑通但代码里全是#TODO: 这里要改和#临时写法别学。而眼前这个Django酒店系统是我近三年见过最“教学友好”的实战模板它不炫技不堆砌高阶特性但每一步都踩在软件工程教学的关键节点上——从用户角色权限的最小可行实现到订单状态机的朴素建模从HTML表单与Django Form的精准对接到views.py里业务逻辑与视图渲染的清晰分界甚至settings.py里DEBUG开关、静态文件路径、数据库配置的注释都像一位坐在你旁边的助教在你敲下python manage.py runserver前就悄悄提醒你“这里别忘改”。核心关键词“Django酒店系统”不是泛泛而谈——它用客户/管理员双角色权限控制替代了空洞的“RBAC理论”用房间-订单-押金三张主表外键约束落地了数据库设计课上的ER图用bookdetail.html里一个select下拉框联动JS刷新价格讲透了前后端数据流“Python课程设计”意味着它拒绝Flask的轻量陷阱学生容易陷入手动拼接SQL也绕开了FastAPI的异步迷宫对初学者纯属超纲坚定选择Django——因为它的models.py就是数据库说明书admin.py开箱即用的后台就是最好的测试工具templates目录下每个.html文件命名都对应一个URL路由这种“所见即所得”的结构比任何PPT都更能帮学生建立Web开发的肌肉记忆至于“酒店预订源码”它没把“预订”做成一个按钮而是拆解成客户查房→选房型→填入住离店时间→校验库存→生成订单→跳转支付模拟→管理员确认→押金登记→报表统计整整七步闭环每一步在views.py里都有独立函数参数怎么传、错误怎么抛、成功怎么跳转全在注释里写得明明白白。如果你正为课程设计发愁或者想用一个真实项目理解Django的骨架这个包不是“能跑就行”的玩具而是你交作业时敢往答辩PPT里贴截图、老师提问时你能指着代码说“这里我改了三次才弄懂”的底气来源。2. 整体架构设计与思路拆解为什么这样搭而不是那样搭2.1 技术栈选型Django不是唯一解但它是教学最优解很多学生第一反应是“用Flask更简单”但简单不等于适合教学。Flask的自由度太高一个app.route()后面可以塞进SQL查询、模板渲染、文件读写初学者根本分不清哪部分该归模型、哪部分该归视图。而Django强制的MVTModel-View-Template分层恰恰是软件工程课反复强调的“关注点分离”。比如models.py里定义Room类class Room(models.Model): room_number models.CharField(max_length10, uniqueTrue) # 房号唯一 room_type models.CharField(max_length20) # 标准间/豪华套房 price_per_night models.DecimalField(max_digits6, decimal_places2) # 单价 is_available models.BooleanField(defaultTrue) # 是否可订非删除标记 capacity models.IntegerField(default2) # 床位数这段代码背后是三层教学意图uniqueTrue教数据库约束defaultTrue教默认值设计is_available字段名直白体现“软删除”思想不真删数据只改状态比status这种模糊字段更适合入门。再看views.py里预订逻辑def book_room(request): if request.method POST: form BookingForm(request.POST) if form.is_valid(): booking form.save(commitFalse) # 关键校验检查房间是否可用、日期是否冲突 if not check_room_availability(booking.room, booking.check_in, booking.check_out): messages.error(request, 该房间在此时段已被预订请选择其他房间或日期) return redirect(customer_book) booking.customer request.user booking.status pending # 状态机起点 booking.save() return redirect(book_success)这里没有一行多余代码form.is_valid()封装了前端传参校验check_room_availability()抽离为独立函数方便单元测试status pending明确订单初始状态messages.error()用Django内置消息框架反馈错误——所有这些都是企业开发中被验证过的最佳实践而学生通过抄写、调试、修改自然内化。提示对比FlaskDjango的forms.py自动生成HTML表单并绑定校验规则省去手写JS正则的麻烦Django Admin后台一行注册就能管理所有数据比自己写CRUD页面快十倍——这些不是“偷懒”而是让学生聚焦在业务逻辑本身。2.2 角色权限设计不用Django-guardian用原生方法够用且易懂项目没引入第三方权限库而是用Django原生的User.is_staff和自定义字段实现双角色。models.py里扩展了用户模型class UserProfile(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE) role models.CharField(max_length10, choices[(customer, 客户), (manager, 管理员)]) phone models.CharField(max_length15, blankTrue)登录后views.py里判断角色只需def customer_index(request): if not hasattr(request.user, userprofile) or request.user.userprofile.role ! customer: return redirect(login) # 非客户角色强跳登录页 # ...客户专属逻辑为什么不用更高级的groups或permissions因为课程设计的核心目标是“理解权限概念”而非“掌握权限框架”。role字段字符串匹配学生一眼看懂is_staff控制能否访问Admin后台天然区分技术权限与业务权限所有角色跳转逻辑集中在urls.py的path()里比如urlpatterns [ path(login/, views.login_view, namelogin), path(customer/, views.customer_index, namecustomer_index), path(manager/, views.manager_index, namemanager_index), # 所有客户路径加前缀所有管理员路径加前缀路由即权限 ]这种设计牺牲了扩展性未来加第三种角色需改代码但换来了绝对的可读性——学生调试时在浏览器地址栏看到/customer/book/就知道这是客户功能看到/manager/report/就知道这是管理员报表不需要查文档、不需要问助教。2.3 数据库设计ER图如何变成三张表以及为什么押金要单独建模课程报告PDF里的ER图核心是三个实体Customer客户、Room房间、Booking订单。但实际models.py里还有Deposit押金表这常被学生忽略。我们来还原设计思考Booking表必须存客户ID、房间ID、入住/离店时间、总金额、状态pending/confirmed/cancelledDeposit表必须存订单ID、押金金额、收取时间、操作员管理员ID关键问题押金能不能直接加在Booking表里比如加个deposit_amount字段答案是不能。原因有三第一业务上押金可能分多次收取比如先收50%入住时再收50%单字段无法记录多次操作第二财务审计要求每一笔押金有独立流水号、操作人、时间戳Booking表混入财务字段会污染业务模型第三Deposit表可关联Booking表的on_deletemodels.CASCADE订单取消时押金记录自动清理避免脏数据。所以models.py里是这样建模的class Deposit(models.Model): booking models.ForeignKey(Booking, on_deletemodels.CASCADE, related_namedeposits) amount models.DecimalField(max_digits8, decimal_places2) collected_at models.DateTimeField(auto_now_addTrue) collected_by models.ForeignKey(User, on_deletemodels.SET_NULL, nullTrue, blankTrue)related_namedeposits让查询变得直观booking.deposits.all()就能拿到该订单所有押金记录。这种设计把“一笔押金”当成独立业务事件而不是订单的附属属性正是数据库范式化的落地体现。3. 核心模块解析与实操要点从登录到报表每一步都在教你怎么写3.1 用户认证模块为什么login.html里没写密码加密逻辑login.html是一个纯前端页面只包含用户名、密码输入框和提交按钮。学生常疑惑“密码加密在哪做”答案在views.py的login_view函数里def login_view(request): if request.method POST: username request.POST.get(username) password request.POST.get(password) user authenticate(request, usernameusername, passwordpassword) # Django自动哈希比对 if user is not None: login(request, user) # 自动设置session # 角色跳转 if hasattr(user, userprofile) and user.userprofile.role manager: return redirect(manager_index) else: return redirect(customer_index) return render(request, login.html)关键点在于authenticate()函数——它接收明文密码内部调用user.check_password()而Django User模型的password字段存储的是pbkdf2_sha256$...格式的哈希值在settings.py里由PASSWORD_HASHERS指定。这意味着- 前端无需写JS加密那只是障眼法抓包照样拿到明文- 后端不用手动调用make_password()那是注册时用的-authenticate()失败返回None成功返回User对象逻辑干净利落。注意register.html里密码输入框是两个确认密码但views.py注册逻辑里只用第一个密码创建用户第二个仅作前端校验。这是故意为之——教学项目优先保证流程正确而非过度防御。真实项目会加PasswordValidation但课程设计阶段让学生先理解“密码怎么存”比“密码多难猜”更重要。3.2 房间预订模块bookdetail.html里的动态价格计算是怎么实现的打开bookdetail.html能看到一个日期选择器和一个实时更新的价格显示区。这不是前端JS算出来的而是Django模板语法驱动的!-- bookdetail.html 片段 -- p您选择的房型strong{{ room.room_type }}/strong/p p入住日期input typedate idcheck_in namecheck_in required/p p离店日期input typedate idcheck_out namecheck_out required/p p预估费用span idtotal_price¥{{ room.price_per_night }}/span按1晚计算/p script document.getElementById(check_out).addEventListener(change, function() { const checkIn new Date(document.getElementById(check_in).value); const checkOut new Date(this.value); const nights Math.ceil((checkOut - checkIn) / (1000 * 60 * 60 * 24)); const price {{ room.price_per_night|floatformat:2 }} * nights; document.getElementById(total_price).textContent ¥ price.toFixed(2); }); /script这里有两个精妙设计第一{{ room.price_per_night|floatformat:2 }}是Django模板过滤器确保后端传来的价格是两位小数避免JS计算出现199.99999999999997第二JS只负责“天数×单价”不碰数据库——真正的库存校验在views.py的book_room函数里完成前端计算只是给用户即时反馈降低跳出率。实操心得我让学生改过这个功能把“按天计费”改成“按小时计费”只需改JS里的计算逻辑和Booking模型的check_in/out字段类型DateTimeField后端校验函数check_room_availability()同步调整时间粒度整个流程无缝衔接。这就是良好分层的价值——改一处不动全局。3.3 订单管理模块allbooked.html如何展示客户所有订单allbooked.html是客户查看历史订单的页面核心是views.py里的all_bookings函数def all_bookings(request): bookings Booking.objects.filter(customerrequest.user).order_by(-created_at) return render(request, allbooked.html, {bookings: bookings})看似简单但藏着三个教学重点-filter(customerrequest.user)Django ORM的链式查询比SQL的WHERE user_id ?更安全防SQL注入-order_by(-created_at)-号表示降序最新订单排第一符合用户直觉- 模板里遍历{% for booking in bookings %}...{% endfor %}自动处理空列表不用if bookings判断。更关键的是Booking模型的__str__方法def __str__(self): return f订单#{self.id} - {self.room.room_number} - {self.check_in}至{self.check_out}这决定了Admin后台和模板里{{ booking }}显示什么。学生第一次看到{{ booking }}输出“订单#123 - 101 - 2024-01-01至2024-01-03”时会突然明白__str__不是装饰而是数据可读性的基础设施。3.4 报表统计模块baobiao.html背后的聚合查询baobiao.html是管理员报表页显示“本月入住率”“各房型收入”“押金总额”。这些不是前端算的而是Django ORM的聚合查询from django.db.models import Sum, Count, Avg, Q from datetime import datetime, timedelta def report_view(request): # 本月入住率 已确认订单数 / 总房间数 × 本月天数 today datetime.today() month_start today.replace(day1) month_end (month_start timedelta(days32)).replace(day1) - timedelta(days1) total_rooms Room.objects.count() booked_nights Booking.objects.filter( statusconfirmed, check_in__ltemonth_end, check_out__gtemonth_start ).aggregate( total_nightsSum(nights) # nights字段在Booking模型里已计算好 )[total_nights] or 0 occupancy_rate (booked_nights / (total_rooms * (month_end - month_start).days)) * 100 if total_rooms else 0 # 各房型收入 revenue_by_type Booking.objects.filter( statusconfirmed, check_in__yeartoday.year, check_in__monthtoday.month ).values(room__room_type).annotate( total_revenueSum(total_amount), countCount(id) ) context { occupancy_rate: round(occupancy_rate, 2), revenue_by_type: revenue_by_type, total_deposit: Deposit.objects.filter( collected_at__yeartoday.year, collected_at__monthtoday.month ).aggregate(Sum(amount))[amount__sum] or 0 } return render(request, baobiao.html, context)这里教的是-aggregate()做跨记录计算求和、计数-values().annotate()做分组聚合类似SQL的GROUP BY-room__room_type双下划线语法穿透外键获取关联表字段-today.replace(day1)这种日期操作比硬写2024-01-01更健壮。实操心得学生常在这里卡住因为nights字段需要提前在Booking.save()里计算。我在models.py的Booking类里加了save()重写def save(self, *args, **kwargs): if self.check_in and self.check_out: self.nights (self.check_out - self.check_in).days if self.nights 0: self.nights 1 # 至少1晚 super().save(*args, **kwargs)这样所有订单创建时自动算好天数报表查询时直接Sum(nights)不用每次查完再循环计算——这就是ORM聚合查询的前提数据要预先规整。4. 实操过程与核心环节实现从零部署到功能验证的完整路径4.1 环境准备与依赖安装为什么requirements.txt里只有四行项目没提供requirements.txt但settings.py和manage.py暗示了最低依赖Django4.2.7 Pillow10.0.1 python-decouple3.8为什么只有这三行因为Django 4.2.x自带SQLite3驱动、模板引擎、ORM等全部核心组件Pillow用于处理头像上传customerindex.html里有头像修改入口python-decouple用于环境变量管理settings.py里config config(DEBUG, defaultFalse, castbool)。学生常犯的错误是pip install django后直接运行结果报错ModuleNotFoundError: No module named PIL——这就是教学意图让你亲手解决依赖问题而不是一键pip install -r requirements.txt。实操步骤Windows/Mac/Linux通用1. 创建虚拟环境python -m venv hotel_env2. 激活环境- Windows:hotel_env\Scripts\activate.bat- Mac/Linux:source hotel_env/bin/activate3. 安装Djangopip install Django4.2.74. 安装Pillowpip install Pillow如报错zlib not available先装系统依赖Macbrew install zlibUbuntusudo apt-get install zlib1g-dev5. 安装decouplepip install python-decouple注意Pillow安装失败90%是因为缺少系统级图像库libjpeg、zlib。不要用pip install --upgrade pip强行升级而是按提示装系统依赖。这是DevOps的第一课环境不是代码但决定代码能否运行。4.2 数据库初始化与迁移testdb.py的作用是什么项目里有个testdb.py文件内容是from django.test.utils import get_runner from django.conf import settings import os os.environ.setdefault(DJANGO_SETTINGS_MODULE, hotel.settings) import django django.setup() # 手动创建测试数据 from django.contrib.auth.models import User from myapp.models import Room, UserProfile # 创建超级用户 User.objects.create_superuser(admin, adminexample.com, 123456) # 创建测试房间 Room.objects.create(room_number101, room_type标准间, price_per_night199.00, capacity2) Room.objects.create(room_number202, room_type豪华套房, price_per_night399.00, capacity4) print(测试数据初始化完成)这不是Django标准做法但极其教学友好。学生运行python testdb.py后数据库里立刻有管理员账号和测试房间不用记createsuperuser命令也不用在Admin后台手动点十次。testdb.py本质是一个“数据种子脚本”比Django的fixtures更直观——所有代码都在一个文件里增删改查一目了然。迁移步骤1. 修改settings.py里的DATABASES确认使用SQLite默认配置python DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } }2. 执行迁移python manage.py makemigrations→python manage.py migrate3. 运行种子脚本python testdb.py4. 启动服务python manage.py runserver此时访问http://127.0.0.1:8000/login/用admin/123456登录就能看到完整的管理员后台。4.3 静态文件配置为什么statics目录要复制到static且settings.py里要改两处项目里statics目录存放CSS/JS/images但Django默认找static目录。这是故意的教学设计让学生亲手配置静态文件路径理解STATIC_URL和STATICFILES_DIRS的区别。settings.py里关键配置# 静态文件URL前缀浏览器请求用 STATIC_URL /static/ # 本地静态文件搜索路径开发时Django去哪里找 STATICFILES_DIRS [ BASE_DIR / statics, # ← 这里指向项目里的statics目录 ] # 生产环境收集静态文件的目标目录课程设计不用管 # STATIC_ROOT BASE_DIR / staticfiles实操步骤1. 将项目根目录下的statics文件夹重命名为static或直接在STATICFILES_DIRS里写BASE_DIR / statics2. 确保STATICFILES_DIRS指向正确路径3. 在模板顶部加{% load static %}引用资源时用link relstylesheet href{% static css/style.css %}提示学生常把STATIC_URL设成/statics/结果浏览器404。记住STATIC_URL是URL路径STATICFILES_DIRS是服务器文件路径二者无关。就像你家门牌号URL和你家实际住址文件路径不是一回事。4.4 功能验证清单按顺序测这七个点确保系统完整可用不要一上来就乱点。按以下顺序验证每个环节都是一个知识点登录跳转访问/login/输入admin/123456应跳转到/manager/输入普通用户账号如customer1/123456应跳转到/customer/。验证角色路由是否生效。房间查询在/customer/页点击“查看房间”应列出所有房间is_availableTrue的房间显示“可预订”False的显示“已满”。验证Room.is_available字段逻辑。预订流程选一个可订房间填入住离店时间如今天和明天提交后应跳转到/book_success/且该房间在列表中变为“已满”。验证check_room_availability()和Booking.save()。订单查看在/customer/页点击“我的订单”应显示刚下的订单状态为pending。验证Booking.customer外键关联。管理员确认用管理员账号登录进入/manager/点击“待处理订单”找到该订单点击“确认”状态应变为confirmed。验证status字段更新和权限隔离。押金收取在管理员订单详情页点击“收取押金”输入金额如100提交后应跳转回订单页下方显示押金记录。验证Deposit模型和外键关联。报表统计访问/manager/report/应显示入住率、各房型收入、押金总额。验证聚合查询和日期范围逻辑。每个点验证失败都对应一个views.py函数或models.py方法。比如第3点失败90%是check_room_availability()里日期比较逻辑写反了第5点失败大概率是manager_index视图里漏了filter(statuspending)。这种“功能点-代码行”的映射正是调试能力的起点。5. 常见问题与排查技巧实录那些让我改了三遍才搞定的坑5.1 “页面空白/500错误”高频原因及速查表现象最可能原因快速定位方法修复方案访问/login/显示空白页urls.py里path(login/, ...)没指向views.py的login_view函数查urls.py确认namelogin的path对应的views.login_view存在检查views.py是否有def login_view(request):确认urls.py导入正确from . import views点击“预订”按钮后跳转到/customer/但没显示成功信息book_room视图里return redirect(book_success)但urls.py没定义namebook_success的路径运行python manage.py show_urls需先pip install django-extensions或手动查urls.py在urls.py添加path(book/success/, views.book_success, namebook_success)并在views.py写空函数def book_success(request): return render(request, book_success.html)baobiao.html报错Booking object has no attribute nightsBooking模型没定义nights字段或save()重写没生效在Django Shell里运行python manage.py shell然后from myapp.models import Booking; bBooking.objects.first(); print(dir(b))确认models.py里Booking类有nights models.IntegerField(default1)字段并在save()方法里赋值实操心得我让学生遇到500错误第一件事不是百度而是看终端里runserver输出的红色错误栈。Django的错误页面会精确到第几行、哪个变量未定义。比如AttributeError at /manager/report/ Booking object has no attribute nights直接去models.py第87行看Booking类比网上搜“Django AttributeError”快十倍。5.2 “样式错乱/图片不显示”的三大元凶元凶一静态文件路径错配现象页面文字正常但按钮没样式、背景图不显示。诊断浏览器F12看Network标签找style.css或logo.png状态码是404。根因settings.py里STATICFILES_DIRS指向了statics但项目里实际是static或反之。修复统一路径名或在STATICFILES_DIRS里写绝对路径os.path.join(BASE_DIR, statics)。元凶二模板没加载static标签现象CSS链接是/static/css/style.css但浏览器请求的是/static/css/style.css却返回404。诊断查看网页源码link标签的href是/static/css/style.css说明{% load static %}已生效但Network里该请求返回404证明Django没找到文件。根因statics/css/style.css文件实际不存在或文件名大小写不符Linux区分大小写。修复确认statics/css/目录下真有style.css且文件名完全匹配Style.CSS≠style.css。元凶三图片路径硬编码现象customerindex.html里头像显示为小图标右键“查看图片”地址是/media/avatar.jpg但404。根因项目没配置MEDIA_URL和MEDIA_ROOTimg src{{ user.avatar.url }}生成的URL无效。修复在settings.py加MEDIA_URL /media/ MEDIA_ROOT BASE_DIR / media在urls.py主路由末尾加from django.conf import settings from django.conf.urls.static import static if settings.DEBUG: urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)然后在statics同级建media目录放测试图片。5.3 “预订总是失败”的底层逻辑排查学生最常卡在预订功能报错信息五花八门但根源就三个逻辑漏洞1日期校验没考虑“当天入住”check_room_availability()函数里写# 错误写法假设check_in check_out if booking.check_in booking.check_out: return False # 正确写法允许当天入住当天退1晚 if booking.check_in booking.check_out: return False逻辑漏洞2库存校验没排除自身订单当客户修改自己的订单时check_room_availability()会把当前订单也算作“已占用”导致无法修改。修复def check_room_availability(room, check_in, check_out, exclude_booking_idNone): conflicting_bookings Booking.objects.filter( roomroom, status__in[pending, confirmed], check_in__ltcheck_out, check_out__gtcheck_in ) if exclude_booking_id: conflicting_bookings conflicting_bookings.exclude(idexclude_booking_id) return conflicting_bookings.count() 0逻辑漏洞3is_available字段没联动更新房间被预订后Room.is_available应该自动设为False但Booking.save()里没写# 在Booking.save()里加 if self.status confirmed: self.room.is_available False self.room.save()踩坑总结我带学生debug时让他们在check_room_availability()函数开头加print(f校验房间{room.room_number}时段{check_in}~{check_out})然后看终端输出。当看到“校验房间101时段2024-01-01~2024-01-02”后紧接着报错就知道问题出在数据库里真有一条冲突订单——顺着这条线索查Booking.objects.filter(room_id101)往往发现是测试数据没清干净。6. 课程报告撰写要点如何把代码变成高分文档6.1 需求分析章节别写“系统要稳定”写“客户3秒内看到房间列表”课程报告PDF里的需求分析常被学生写成“系统应具备良好的稳定性、可扩展性、安全性”。这种套话老师一眼扫过。高分写法是把功能点翻译成用户场景功能性需求客户能在首页3秒内看到所有可订房间对应Room.objects.filter(is_availableTrue)查询优化客户填写入住离店日期后页面实时显示预估费用对应bookdetail.html里的JS计算管理员确认订单后客户手机收到短信通知项目没做但可写“预留短信接口调用阿里云SMS SDK”非功能性需求并发支持单台笔记本运行支持20人同时在线Django开发服务器默认支持数据安全密码采用Django PBKDF2哈希存储无明文密码截图auth_user表的password字段可维护性所有业务逻辑集中在views.py模型定义在models.py符合MVT分层附目录结构图。6.2 ER图与数据库表结构用Django命令生成真实SQL别手动画ER图。用Django自动生成python manage.py graph_models myapp -o er_diagram.png # 需pip install pydot # 或直接看SQL python manage.py sqlmigrate myapp 0001表结构描述要带字段含义比如| 字段名 | 类型 | 是否为空 | 默认值 | 说明 ||--------|------|----------|--------|------||room_number| VARCHAR(10) | 否 | — | 房号唯一索引如”101” ||is_available| BOOLEAN | 否 | TRUE | 软删除标志TRUE表示可订FALSE表示已满或维修 |提示在报告里贴出python manage.py showmigrations的输出证明所有迁移已应用比写“数据库已配置”有力得多。6.3 功能测试截图截什么图老师才觉得你真做了不要截“系统首页”这种废话图。截这五张登录跳转验证图浏览器地址栏显示/login/输入admin/123456后地址栏变为/manager/页面显示“管理员欢迎”预订冲突验证图选房间101填入住2024-01-01、离店2024-01-02提交后弹出红色提示“该房间在此时段已被预订”订单状态流转图同一订单在客户页显示pending在管理员页点击“确认”后客户页刷新显示confirmed报表数据图baobiao.html页面右上角显示“本月入住率65.2%”下方表格有“标准间¥12,300.00”Admin后台图/admin/页面Booking列表里有5条记录status列显示不同状态证明数据真实存在。每张图下面用一句话说明“图X验证了XX功能对应views.py第XX行代码”。6.4 总结反思章节别写“收获很大”写“我重构了三次views.py”高分总结要具体、有细节、带成长感技术收获“最初我把所有逻辑写在views.py的一个函数里导致预订失败时无法定位是校验问题还是保存问题。重构后将check_room_availability()、calculate_total()、send_notification()拆成独立函数每个函数职责单一单元测试覆盖率从0%提升到70%。”设计认知“以前认为‘软删除’就是加个is_deleted字段这次用is_available才明白业务字段要贴近场景。is_availableFalse比is_deletedTrue更能表达‘房间暂时不可订’的业务语义。”协作意识“在Git提交时我养成了写清晰commit message的习惯如‘fix: 修复预订日期校验逻辑允许当天入住’而不是‘update files’。这让我在回溯bug时节省了大量时间。”最后分享一个小技巧答辩前把git log --oneline -n 20的输出贴到报告最后一页。20条commit记录每条都对应一个功能点或bug修复比任何文字都证明你真的动手写了代码。这个Django酒店系统表面是一套源码内核是一套软件工程思维训练。它不教你最炫的新框架但教会你如何把一个模糊的需求拆解成可执行的代码模块不承诺“一键上线”但确保你每改一行都明白它在系统中的位置和作用。当你交上这份课程报告老师看到的不仅是功能实现更是你开始像工程师一样思考的证据——而这才是课程设计真正的终点。本文还有配套的精品资源点击获取简介这个Python酒店管理系统用Django框架开发支持客户和管理员双角色操作包含注册登录、房间查询与预订、订单管理、押金收取、报表统计等实用功能。前端页面齐全有login.html、register.html、customerindex.html、managerindex.html、bookdetail.html、baobiao.html等10多个HTML模板配合独立的CSS、JS和图片资源交互清晰。后端代码结构规范models.py定义了用户、客房、订单等核心数据模型views.py封装业务逻辑urls.py完成路由分发settings.py配置基础参数所有模块在本地环境实测可运行。压缩包里还附带一份完整的课程报告PDF涵盖需求分析、ER图设计、数据库表结构、各功能页面测试截图及开发总结内容详实、注释充分适合软件工程或Web开发课程期末作业使用也适合作为Django入门实践参考。本文还有配套的精品资源点击获取