基于Python Django与Vue的酒店管理系统毕业设计开发指南
2026/9/1 14:52:22 网站建设 项目流程

简介:本资源是一套完整的本科毕业设计项目,面向计算机相关专业学生及Web开发初学者,聚焦酒店业务数字化管理需求,提供从前端交互到后端逻辑、数据库设计与文档交付的全栈实践方案。压缩包为ZIP格式,共包含源码工程、开题报告、毕业论文与配套视频教程等核心内容,总大小58.18MB;其中Django后端项目含完整RESTful API接口与MySQL数据模型,Vue前端实现响应式前台浏览、用户预定、入住管理等模块,文档类文件涵盖选题依据、系统设计思路与实现细节,视频教程则演示环境搭建、功能调试与部署流程。目前已有99人学习下载,适合用于课程设计参考、毕设快速启动或Django+Vue前后端分离架构的实战训练,尤其便于理解客房预定流程、权限分级(游客/用户/员工/管理员)与多角色协同管理等典型业务场景。 如果毕业设计选的是管理系统方向,那第一道坎基本都在技术选型上。Java的Spring Boot确实强,但学习周期摆在那;PHP又显得有点不够看。Python+Django+Vue+MySQL这套组合,恰好卡在一个很舒服的位置:技术栈足够主流、生态成熟、学习曲线适中,而且做出来的东西在答辩时说起来也拿得出手。这篇文章我就把酒店管理系统的完整开发思路拆开讲一遍,从技术选型背后的逻辑、数据库怎么设计、前后端怎么对接,到论文和开题报告怎么写、有哪些坑一定要避开,一次性说清楚。

这套项目我做下来最大的感受是,它不是一个“写代码”的题目,而是一个“规划”的题目。只要前期把表结构、接口约定、状态流转这三件事想明白,后面所有代码就是填表格而已。反过来,如果连订单状态该有哪些值都没想清楚就冲冲冲写代码,那改起来真的会怀疑人生。下面我按自己当时走的路线,把每个环节的思考过程都记录下来,希望能帮你少踩几个坑。

1. 选题与技术选型:毕业设计最不该偷懒的一步

1.1 酒店管理系统到底在管理什么

很多人一听“酒店管理系统”就觉得烂大街,这恰恰是它的优势。毕业设计不是创业项目,它要的是“需求清晰、逻辑完整、可以论证”。酒店管理系统天然就有一套成熟业务模型,你可以很顺畅地把需求分析、数据库设计、系统测试这些论文必备章节写扎实。

那这套系统到底要管什么?拆开看就是三件事:管房间、管订单、管用户。房间有房型、价格、楼层、状态;订单有预订、入住、退房、取消;用户有顾客、前台、管理员三种角色。这个业务模型足够复杂,能体现你的系统设计能力,但又没有复杂到一个人做不完。我见过有人非要选“大型分布式电商平台”,结果光商品SKU就绕晕了,答辩时连核心流程都讲不清楚,那就是自己给自己挖坑。

1.2 技术栈选型的真实逻辑

Python+Django+Vue+MySql这个组合,每一个选型都有明确的理由,不是随大流。Django能火这么多年,核心是它的“全家桶”理念——ORM、Admin后台、认证系统、表单校验全给配齐了。对于毕业设计这种周期紧、要出成果的项目,这种“开箱即用”的特性非常关键。

而Vue作为前端框架,最大的好处是上手曲线平缓。你不需要理解虚拟DOM的底层原理,照着模板语法写就能干活。Element UI组件库更是把表格、表单、弹窗这些后台系统高频组件全都封装好了,拖拖拽拽就能拼出一个管理界面。MySQL就更不用说了,市场占有率最高,网上教程多到看不完,出什么问题都能搜到答案。这三样组合在一起,就是给毕设量身定做的“舒适区”。

1.3 为什么必须用前后端分离架构

很多学校的毕设系统还停留在Django模板渲染那套老路上——一个views函数又查数据库又拼HTML又处理表单提交。这种写法做小demo没问题,但要做成能展示的项目,前后端分离是必须的。

前后端分离的核心是“职责分开”。后端只负责提供JSON数据接口,前端只负责页面渲染和用户交互。这样做最直接的好处是开发效率高——你可以在两周内把后端所有接口写完,然后用Postman测通,再花两周专心怼前端页面,遇到问题不用在两个端之间反复横跳。而且答辩的时候,面试官问一句“为什么采用前后端分离”,你就能从维护性、扩展性、团队协作三个角度讲出东西来,这比单纯说“我用了这个框架”要加分得多。

2. 数据库设计:一套能撑住论文的系统,地基不能糊弄

2.1 核心数据表结构逐张拆解

数据库设计是毕设的重中之重,因为论文里的E-R图、数据字典、关系模式都从这里来。我建议不要偷懒直接跑别人的SQL脚本,而是自己理解每一张表的用途,哪怕最后结构跟网上的差不多,你也能在答辩时讲明白“为什么这么设计”。

我当时设计的核心表大概是这几张:

表名核心字段作用说明
userid, username, password, real_name, phone, role系统用户表,role区分顾客(0)、前台(1)、管理员(2)
room_typeid, name, price, area, bed_type, max_people, image, description房型表,比如大床房、双床房、套房
roomid, room_number, room_type_id, floor, status房间表,status区分空闲(0)、已入住(1)、维修(2)
ordersid, order_no, user_id, room_id, check_in_date, check_out_date, total_amount, deposit, status订单主表,记录每次预订/入住的核心信息
check_recordid, order_id, room_id, check_type, operator_id, create_time入住退房操作记录表,做审计和报表用

这里有个细节值得展开。订单总数amount、实际支付paid_amount、押金deposit这三个金额字段,我建议分开存,不要只放一个total_price。原因很简单,现实业务中经常出现“预收押金、退房时再算总账”的情况,而且有时前台会给折扣,如果只存一个字段,后面想追溯就很麻烦。虽然毕设系统的复杂度到不了财务级别,但多一个字段会让你的设计看起来更专业,论文里也能多写一段说明。

2.2 状态字段设计:用整型常量,别用布尔值硬扛

订单状态是这套系统里最容易翻车的地方。新手很容易写一个is_paid布尔字段,然后发现根本不够用——因为订单不只是“付没付钱”,它还有“已预订”“已入住”“已退房”“已取消”这些阶段。

我的做法是给订单设计一个整型状态字段,并在后端定义常量类统一管理:

class OrderStatus: PENDING = 0 # 待支付 PAID = 1 # 已支付/待入住 CHECKED_IN = 2 # 已入住 CHECKED_OUT = 3 # 已退房 CANCELLED = 4 # 已取消

不光要有状态值,还要明确状态流转的规则。我总结了一套最简单的流转逻辑:

  • 用户提交预订 -> 订单生成,状态为待支付(0)
  • 用户支付成功 -> 状态为已支付(1),此时房间被预占
  • 前台办理入住 -> 状态为已入住(2),房间状态改为已入住
  • 前台办理退房 -> 状态为已退房(3),房间状态改为空闲
  • 用户在支付前取消 -> 状态为已取消(4)

这里最需要注意的一点是,房间状态和订单状态是两套体系,要同步更新但不能混在一起。我用一张表说明它们的关系:

订单状态对应房间状态说明
待支付/已支付房间仍空闲,但被“锁住”(可用但不可再订)可以继续保留房间
已入住房间已入住房间表 status 置为 1
已退房/已取消房间空闲房间表 status 置为 0

千万不要为了省事,把房间状态直接存进订单表里,那是反范式设计,后面联调时数据不一致的坑会一个接一个。

2.3 一对多、多对多关系怎么落表

酒店管理系统的实体关系其实很清晰,主要就两种:房型对房间是一对多,一个房型下有多个房间;用户对订单是一对多,一个用户可以有多笔订单。订单和房间是多对一,一个房间在不同时间段可以被不同订单使用。

理解关系之后,外键设计就顺理成章了。room表里放一个room_type_id外键指向room_type的主键,orders表里放user_id和room_id分别指向user和room。这里要提醒一句,Django的ORM里定义外键用models.ForeignKey,在数据库层面会自动创建索引,所以在ORM层面做关联查询时效率是有保障的,不需要你手动去建冗余字段。

还有一个容易被忽视的点:订单号order_no不要直接用自增主键,最好单独生成一个带时间戳的唯一订单号,比如202411202130001这种。这样用户在订单列表页看到的是可读的编号,而不是id=123,更符合真实业务习惯。

3. 后端开发:Django接口层怎么写才不算白学

3.1 环境搭建与项目初始化

后端我建议直接使用Django REST Framework(DRF),它比裸写Django JsonResponse要舒服太多。先创建一个虚拟环境再装依赖,避免把系统Python环境搞乱:

# 创建虚拟环境 python -m venv venv # 激活(Windows和Linux/macOS命令不同,这里写Windows的) venv\Scripts\activate # 安装依赖 pip install django djangorestframework django-cors-headers pymysql pillow djangorestframework-simplejwt

有几个包的作用值得说一下。django-cors-headers是用来解决跨域问题的,前后端分离开发时这是必装;pymysql是让Django连MySQL用的驱动,记得要在项目的__init__.py里加上pymysql.install_as_MySQLdb(),否则会报找不到MySQLdb;pillow是处理图片上传的,房型图要用到。

数据库连接配置在settings.py里,关键是把原来默认的sqlite数据库替换掉:

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'hotel_db', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', } } }

这里有个实际经验:MySQL 8.0默认的认证插件是caching_sha2_password,老版本的pymysql连上去可能报错。如果你在连接时遇到Authentication plugin 'caching_sha2_password' cannot be loaded,就在MySQL里执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';,问题就能解决。

3.2 JWT认证:前后端分离下的登录方案

传统Django的Session认证在前后端分离模式下不太好用,因为跨域场景下Cookie的处理比较麻烦。我采用的是JWT(JSON Web Token)方案,用djangorestframework-simplejwt这个库实现,前后端各拿各的Token做身份验证,符合现代接口开发习惯。

在settings.py里配置认证类:

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), }

然后在urls.py里挂上获取Token和刷新Token的接口:

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView urlpatterns = [ path('api/auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('api/auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), ]

登录接口前端会拿到access和refresh两个Token。这里有个习惯要养成:数据库里存的用户密码一定是哈希值,绝对不能用明文。Django自带的make_passwordcheck_password就够用,Token签发时它会自动校验。我见过有同学在user表里直接存明文密码,简直是用生命在演示安全问题。

要注意的是,JWT的access Token有效期通常设短一点,比如30分钟或2小时,refresh Token有效期可以长一些,比如7天。前端拿到401响应后,要用refresh Token去换新的access Token。这个过程不复杂,但一定要在DevTools的Network面板里看到接口返回401时能反应过来是Token过期了,而不是慌慌张张去改后端代码。

3.3 核心接口的编写逻辑:预订、入住、退房

接口设计上,我推荐走“轻服务”路线——一个ViewSet对应一张核心表,加上自定义action处理特殊业务。以订单为例,用一个OrderViewSet,基础的增删改查交给DRF的ModelViewSet自动生成,再额外定义两个action:

class OrderViewSet(viewsets.ModelViewSet): queryset = Order.objects.all().order_by('-create_time') serializer_class = OrderSerializer @action(detail=True, methods=['post']) def check_in(self, request, pk=None): order = self.get_object() if order.status != OrderStatus.PAID: return Response({'error': '订单状态不允许入住'}, status=400) order.status = OrderStatus.CHECKED_IN order.save() room = order.room room.status = RoomStatus.OCCUPIED room.save() return Response({'message': '入住成功'}) @action(detail=True, methods=['post']) def check_out(self, request, pk=None): order = self.get_object() if order.status != OrderStatus.CHECKED_IN: return Response({'error': '订单状态不允许退房'}, status=400) order.status = OrderStatus.CHECKED_OUT order.save() room = order.room room.status = RoomStatus.AVAILABLE room.save() return Response({'message': '退房成功,欢迎再次光临'})

这里有两个关键点。第一,所有状态变更的接口必须做状态校验,不能允许从“待支付”直接跳到“已退房”,否则数据就乱了。第二,订单状态和房间状态的同步更新必须放在同一个请求里完成,不能用两个接口分开调,否则中间崩了就会出现“订单已入住但房间还是空闲”的数据不一致情况。

房间查询接口同样重要,我提供了两个查询维度:一个按日期查可用房间,接收check_in_date和check_out_date参数,排除日期冲突的订单;另一个按房型查列表,返回房型信息含最早可用日期。用户下单时,后端必须再次校验这个房间在目标时间段内是否真的可用,防止并发下单。

3.4 接口调试与文档

接口写完之后不要直接开前端,先用Postman把所有接口测一遍。测的时候重点关注三件事:第一,未登录访问受保护接口能不能正确返回401;第二,传非法参数时后端会不会返回友好的错误信息而不是500;第三,核心业务流程的接口调用顺序是否流畅。

DRF自带的可浏览API文档也值得一提。开发模式下,你在浏览器里访问http://localhost:8000/api/,可以看到所有接口的列表,还能直接在页面上做请求测试。这个功能在毕设演示的时候特别有用,你可以现场给评委演示“看,这是我们的订单接口,传这几个参数就能创建一个新订单”。比只截图代码有说服力多了。

4. 前端开发:Vue这层要的是把复杂变简单

4.1 页面与路由设计

前端项目的目录结构我建议按“视图(views)+组件(components)+工具(utils)”三层组织。views里放页面级组件,components里放通用组件,utils里放axios封装、日期格式化这些工具函数。

页面路由规划上,酒店管理系统的核心页面大概是这些:

路由路径页面角色
/login登录页所有用户
/首页布局(含侧边栏和顶栏)登录用户
/rooms房间列表与房型展示所有登录用户
/rooms/:id房间详情所有登录用户
/orders我的订单普通用户
/admin/orders订单管理(预订/入住/退房操作)前台/管理员
/admin/rooms房间管理管理员
/admin/users用户管理管理员

这里要特别说一个点:路由的懒加载能省不少首屏时间。Vue Router支持直接把页面组件写成component: () => import('../views/AdminOrders.vue'),这样每个路由对应的组件会在访问时才加载,而不是一次性把整个应用都下下来。这个细节写进论文“系统性能优化”一节,还是挺加分的。

4.2 Axios封装与Token的存放

前端调用后端接口,axios是绕不开的。我建议封装一个request.js,统一配置baseURL、请求超时时间、请求拦截器和响应拦截器。核心代码如下:

import axios from 'axios' import router from '../router' const request = axios.create({ baseURL: '/api', timeout: 10000 }) // 请求拦截器:自动带上Token request.interceptors.request.use(config => { const token = localStorage.getItem('access_token') if (token) { config.headers.Authorization = 'Bearer ' + token } return config }) // 响应拦截器:统一处理错误码 request.interceptors.response.use( response => response.data, error => { if (error.response && error.response.status === 401) { // Token过期,跳转登录页 localStorage.removeItem('access_token') router.push('/login') } return Promise.reject(error) } ) export default request

这里有个实操经验:Token到底存localStorage还是sessionStorage,网上争议很大。对于毕设项目,存localStorage就够了,因为刷新页面后Token还能保留,体验更好。另外,在开发模式下,baseURL建议用相对路径/api,配合Vue开发服务器的proxy代理把请求转发到Django的8000端口,这样就能绕开复杂的前端跨域问题,vite或vue-cli里一行配置就搞定。

// vue.config.js 或用 Vite 的 server.proxy module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8000', changeOrigin: true } } } }

4.3 权限控制怎么做

权限控制是前后端分离项目里最容易出问题的环节。前端要控制“有没有某个按钮、能不能进某个页面”,后端要控制“这个接口允不允许你访问”,两层缺一不可。

后端权限已经在DRF里通过IsAuthenticated和自定义权限类搞定了。前端这边,登录成功后拿到用户角色role,我把它存进Vue的状态管理仓库,然后做三件事:

第一,路由守卫。在路由配置的meta里标记需要的角色,比如meta: { roles: ['admin', 'staff'] }。路由跳转前,在全局前置守卫里判断当前用户角色是否在允许列表内,不在就跳转到一个401页面或首页。

第二,菜单过滤。首页侧边栏的菜单项,根据角色动态生成。普通用户只看到“房间浏览”和“我的订单”;前台多一个“订单管理”;管理员额外看到“用户管理”和“房型管理”。

第三,按钮级权限。比如前台的“办理入住”按钮,管理员也能看到;普通用户则看不到。这个用自定义指令v-permission来实现,比在每个组件里写死v-if要优雅得多。

4.4 组件化思维:把表单、表格、弹窗拆开写

写Vue最忌讳的就是一个页面塞几百行模板。我自己的经验是,只要是出现两次以上的结构,就应该抽成组件。比如“订单状态标签”,不同状态显示不同颜色,这个我们抽一个OrderStatusTag.vue;再比如“房间卡片”,列表页和详情页都可能用到,抽一个RoomCard.vue

拿订单管理页面举例,它实际上就是“一个筛选表单+一个订单表格+若干操作弹窗”的组合。筛选表单可以抽成OrderFilter.vue,表格用Element UI的el-table封装数据展示,操作弹窗再按“预订”“入住”“退房”拆成独立组件。这样每个组件的职责单一,出问题的概率小,答辩时你也可以讲“我的前端采用了组件化开发,每个组件都遵循高内聚低耦合的原则”,这种专业表达是能加分的。

5. 联调、部署与测试:系统能跑起来,只是第一步

5.1 跨域问题的根治方案

前后端分离开发中,跨域是最常见的问题。开发环境下的方案我已经讲了,就是用Vue的proxy代理把请求转发到后端,这属于“前端解决法”。但如果你想把前端打包后发给别人看,或者部署到服务器上,那就必须从后端解决。

最简单的后端方案就是用之前提到的django-cors-headers。安装后在settings.py里配置:

CORS_ALLOWED_ORIGINS = [ "http://localhost:8080", "http://127.0.0.1:8080", ]

这表示允许来自这两个前端的跨域请求。用cors-headers的时候,有几个小坑我之前踩过:一是不要直接用CORS_ALLOW_ALL_ORIGINS = True,虽然调试方便,但论文里写出去不好看,而且有安全隐患;二是如果用了JWT认证,一定要在CORS配置里把CORS_ALLOW_HEADERS加上Authorization,否则前端带上Token的请求会被跨域策略拦下来。

还有个小技巧,联调时如果遇到“状态码200但前端拿不到数据”,十有八九是响应头里的Content-Type不对,或者跨域预检请求(OPTIONS)没通过,先打开DevTools看Network面板,再看后端日志,别一上来就怀疑代码逻辑。

5.2 部署流程梳理

毕设答辩前,我强烈建议把系统部署到一台云服务器上或者至少用Docker跑起来,这样演示的时候不用当着评委的面开两个终端敲启动命令。一个完整的前后端分离部署方案是这样的:

  • 前端:用npm run build打包成静态文件,交给Nginx托管。
  • 后端:用gunicorn运行Django应用,监听8000端口。
  • 接口转发:Nginx把/api开头的请求反向代理到localhost:8000
  • 数据库:MySQL单独运行,确保Django配置里的数据库地址、账号密码和生产环境一致。

部署这件事不需要搞得很复杂,但一定要提前演练一次。我见过太多同学,在本地跑得好好的,一到演示就各种404,原因基本都是前端打包后静态资源路径不对,或者Nginx配置的proxy_pass末尾少了个斜杠。这些都是细节,但毁灭性极强。

5.3 测试用例设计思路

毕设论文里的“系统测试”章节,完全不需要你用自动化测试框架写几百个用例,重点是能证明系统是可靠的。我建议从三个层次来做测试:

功能测试:把核心业务流程整个跑一遍。注册新用户→登录→搜索房间→下单→模拟支付→前台入住→前台退房,每个环节都截图保存,这些截图可以贴进论文。

接口测试:核心接口至少覆盖正常参数、异常参数、未登录状态、无权访问四种情况。DRF会自动拦截权限问题,返回401,这个截几张图展示即可。

兼容性测试:分别用Chrome和Edge打开前端页面,确认页面布局和交互没问题。如果时间允许,再用手机浏览器看看布局,毕竟现代项目不能完全忽略移动端。

这三部分做下来,论文的“测试”一章基本就齐了,而且全是真实数据,不是编的。

6. 开题报告、论文与答辩:毕业设计的一半分数在这

6.1 开题报告怎么写才能一遍通过

很多学校要求先交开题报告,这一关的核心不是写得多,而是证明“你清楚自己要做的是什么”。我见过的开题报告模板五花八门,但核心要素就那么几个:选题背景与意义、国内外研究现状、主要研究内容、技术路线、进度安排。

选题背景不用写太多空话,直接说“随着旅游业的复苏,酒店行业对信息化管理的需求越来越强烈,传统的人工管理方式效率低、易出错,因此设计一套酒店管理系统具有实际意义”就足够了。研究现状这块,可以从“国外酒店管理系统起步早、功能成熟,国内中小型酒店普遍存在信息化程度不高”这个角度切入,不一定要引用特别高深的文献,但一定要有。

最容易被批的是“研究内容”写得太泛。比如“实现酒店管理的基本功能”,评委看了等于没看。正确写法是拆成几条,比如“设计并实现基于B/S架构的酒店管理系统,包括用户管理、房型管理、订单管理、入住退房管理五个核心模块;基于角色实现权限控制,支持三种角色的差异化功能视图”。这样一句话就能让你的开题报告通过率提升一大截。

6.2 毕业论文的章节结构与写作节奏

论文结构一般学校会给模板,但万变不离其宗的骨架是:绪论、需求分析、系统设计、系统实现、系统测试、总结。我强烈建议你在写代码之前就把论文大纲列出来,而不是等项目做完再硬凑。因为大纲会帮你画边界,写着写着发现某个模块做复杂了,你会自觉地砍需求,保证系统在可控范围内。

几个关键章节的写作心得:

需求分析章节,要把用例图画出来,文字说明每个角色能做什么操作。这部分最简单,但也是评分老师看得最仔细的部分。

系统设计章节,重点是数据库表结构和E-R图。每一张表都要在数据字典里列出字段名、类型、约束、说明。这里就是前面数据库设计部分的价值所在,你只要把当时的表结构整理成表格,就基本成型了。

系统实现章节,不要罗列大段代码,要提炼“关键代码”,每一段代码配一段“这段代码解决了什么问题”的解释。评阅老师不关心你写了多少行代码,关心的是你会不会讲代码。

写论文的节奏上,我建议“代码完成70%时开始写架构设计”,因为那时候你对系统的整体结构已经有感觉了。等全部写完了再补需求分析和测试截图。这样做的好处是最后一周只需要做微调,不用熬夜赶工。

6.3 答辩演示的实战建议

答辩演示是最能拉开分差的环节。我见过准备充分的同学直接被评委点头,也见过代码写得不错但一上台就乱了阵脚的同学。讲几个实操建议:

第一个建议,准备一条完整的“业务主线”。不要上来就介绍功能列表,而是模拟一个用户使用场景:一个顾客打开系统,注册登录,浏览房型,预订一间房并支付,然后前台收到新订单,办理入住,最后顾客退房。这条线跑下来,系统所有核心功能都被串起来了,评委听着也轻松。

第二个建议,提前准备可能被追问的问题。酒店管理系统被问最多的就是这几个:“订单状态怎么流转的?”“并发下同一间房被两个人订了怎么办?”“用户密码是怎么保护的?”“如果用户住到一半要换房,你怎么处理?”前三个问题我前面都讲到了,第四个可以提前想一笔,哪怕你只实现了“先退房再订新房”,能自圆其说就行。

第三个建议,别花太多时间讲细节功能。评委不会关心你某个表单校验怎么写,他们关心的是系统的架构、数据模型、安全性、以及你对核心业务逻辑的理解。所以演示时重点讲设计思路,代码细节留在论文里展示即可。

7. 常见问题与避坑速查

7.1 环境搭建阶段的坑

开发环境问题是消耗时间最多的地方,我把高频问题整理成了一张速查表:

问题原因解决方案
Django启动报ModuleNotFoundError: No module named 'MySQLdb'没有在__init__.py里声明使用pymysql在项目__init__.py中加入import pymysql; pymysql.install_as_MySQLdb()
MySQL连接报错2059MySQL 8.0默认认证插件不兼容在MySQL中执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';
Vue启动报Node版本过低Vue CLI或Vite要求Node.js 12以上升级Node.js到LTS版本
后端接口访问数据库时有中文乱码数据库字符集不是utf8mb4建库时指定CREATE DATABASE hotel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

这里我要特别强调一下虚拟环境的重要性。有同学到了答辩前一天环境崩了,就是因为pip install装到了全局环境,结果版本冲突没法启动。从头开始就用虚拟环境,项目换机器迁移也方便——把requirements.txt导出来,新机器执行pip install -r requirements.txt就完事。

7.2 Django与MySQL的坑

Django ORM用起来爽,但深入使用还是有几个容易踩的坑。第一是时间字段的默认值,很多表都要记录create_time,我建议用timezone.now而不是datetime.now,因为后者拿到的是本地时间,前者才是UTC时间,部署到服务器上时时间显示才正常。

第二是DateTimeField的auto_now和auto_now_add不要混用,否则修改记录时时间会被自动重置,你很难发现。更推荐的做法是手动在save方法里维护:

class Order(models.Model): create_time = models.DateTimeField(default=timezone.now) update_time = models.DateTimeField(auto_now=True)

第三是删除操作。Django的Model.objects.filter().delete()默认是软删除还是硬删除?答案是硬删除,直接DELETE从数据库里删掉。如果你希望在订单列表里查历史订单,删除订单会导致数据永久丢失。我当时就遇到过,用户不小心取消了订单,结果订单从数据库里消失,统计报表对不上账。后来我把“取消订单”设计成了更新状态字段为CANCELLED,而不是物理删除。这是一个非常典型的“逻辑删除 vs 物理删除”问题,论文里可以专门写一段。

7.3 Vue与联调的坑

前端开发中,Vue的几个老坑值得提前说。一是路由模式,如果你的前端是打包后部署到Nginx的,路由用createWebHistory模式时,刷新二级路由页面会出现404。这是因为Nginx没有做try_files配置。最省事的方案是用createWebHashHistory,URL里带个#号虽然不好看,但刷新永远不会有问题。

二是图片加载问题。房型图片上传到后端后,后端返回的URL如果是一个相对路径,前端直接写<img :src="roomType.image">很可能加载不出来。最简单的处理方式是在axios封装里配一个图片前缀,或者在后端序列化器里直接转为完整URL。

三是Element UI的Table组件,用el-table的时候注意给每一列都加上prop属性,否则数据不会渲染。这个看起来像废话,但很多人第一次写都栽在这个上面,而且报错信息还特别隐晦。

7.4 进度管理与心态

最后我想聊聊技术之外的东西。毕业设计的时间跨度通常是整个学期,很多人前面两三个月完全不动,然后最后两周一通宵。这套打法不是不行,但出来的质量一定不高。

我当时的节奏是:前两周搞定需求和数据库设计,中间一个月专门写后端接口,再用两周写前端页面,最后留两周联调、写论文、准备答辩。每个阶段结束同步更新一下论文相关章节,这样压力始终是均匀的。如果你已经错过了这个节奏也没关系,至少保证从现在开始,每周末都有新的成果产出,哪怕只是描述文件里多了几段文字截图也比空转要强。

还有一个很实用的建议:每天写代码之前,先花五分钟想清楚“今天要完成什么、怎么测”,写完代码不管多晚,都把当天改动的文件提交到Git仓库。毕设这个周期,Git不只是代码备份,它是你的心理保险——万一某天把系统改坏了,还能一键回退到上个版本,这种安全感是实际存在且非常重要的。

做这套系统下来,我最深的体会是“设计先行”这四个字的分量。数据库设计好了,后端代码其实就是套模板;后端接口约定清楚了,前端联调基本不会有大变动;论文框架提前拉好,最后写起来就是填空。整个项目最难的从来不是某个技术难点,而是你能不能控制住自己东写一笔西写一处的冲动,把每个环节做扎实。顺着这条路走,你会发现毕业设计真的没有想象中那么可怕。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询