在线点餐系统毕业设计实践:微信小程序与Django后端开发全解析
2026/8/29 9:10:14 网站建设 项目流程

简介:Web开发与移动端技术的融合正在改变传统餐饮行业的服务模式。在软件开发领域,前后端分离架构已成为主流,前端通过微信小程序提供轻量级交互体验,后端则借助Django框架快速构建稳定的业务逻辑。微信小程序凭借其开发成本低、生态成熟、分发便利等优势,成为校园项目与中小企业原型验证的热门选择;而Django自带Admin后台和ORM机制,能大幅提升API开发效率。从用户登录、菜品浏览到购物车与订单流转,系统设计需兼顾数据一致性、事务处理和接口安全。JWT认证机制保障了用户身份的可靠性,车辆状态与价格快照的设计则体现了电商系统的核心原则。本文围绕在线点餐系统的完整开发流程,深入解析数据库设计、接口封装、联调部署及常见问题排查,为初学者提供一个从零落地的全栈实践参考。

1. 项目整体设计与技术选型思路

毕业设计选“在线点餐”这个题目,说实话是看了很多届学长学姐的经验之后才定下来的。不是因为它多高大上,而是因为它涵盖的知识点非常完整——有用户端交互、有业务逻辑、有后台管理、有数据库设计,最关键的是生命周期可控,三个月时间足够把核心功能做完、写好论文、做出答辩演示。

这个项目确定下来的技术栈是:前端微信小程序后端Python + Django。很多同学纠结要不要上vue或react做一个后台管理页面,我的结论是:除非你确实学有余力,否则别加。毕设的评审重点是你的业务逻辑是否完整、数据库设计是否规范、前后端交互是否顺畅,而不是页面数量。把小程序端的体验做扎实,比多做一套后台界面更划算。

1.1 为什么是微信小程序而不是原生App或H5

选微信小程序作为前端载体,主要是三方面考虑。

第一是开发成本。小程序使用WXML + WXSS + JavaScript,语法接近H5,有前端基础的人一两周就能上手。原生安卓或iOS开发不仅要学两套语言,还要处理机型适配、应用商店审核这些额外成本,作为一个毕设项目来说性价比不高。

第二是分发与演示方便。答辩的时候,老师用微信扫一个体验版二维码就能在手机上直接看效果,不需要安装APK,不需要连接开发工具。这台设备能跑,换一台设备也能跑,能减少很多“在你电脑上没问题,在我电脑上就报错”的尴尬。

第三是生态成熟。微信登录、支付(虽然毕设一般不做真实支付)、地图定位、图片上传这些都有官方API,而且社区里踩坑记录非常多,出了问题基本都能搜到答案。这一点在赶论文的时候尤其重要——没有什么是比“文档齐全”更让人安心的了。

Django这边同理。它自带的Admin后台能让你免费拿到一套数据管理界面,虽然样式朴素了点,但拿来演示“商家管理菜品”这个场景完全够用。配合Django REST Framework(DRF)写API,整个后端的开发量比Spring Boot能省三分之一左右,这对时间紧张的大四学生来说是实打实的优势。

1.2 在线点餐系统的核心业务模块

开工之前先把业务边界划清楚,这是整个项目最重要的一步。在线点餐听起来简单,但如果不加控制地发散,你会发现自己居然要做购物车、订单、支付、优惠券、会员积分、配送调度……一个比一个复杂。

我的做法是只保留三个端、五条核心链路:

  • 用户端(小程序):浏览菜品、加入购物车、提交订单、查看订单状态、个人资料修改。
  • 商家端(Django Admin):菜品分类管理、菜品上下架、订单状态流转(待接单 → 制作中 → 已完成)。
  • 公共模块:用户登录(微信授权 + 手机号绑定)、文件上传(菜品图片)。

五条核心链路分别是:用户登录流程、菜品浏览流程、购物车加购流程、下单流程、订单状态流转流程。其余的功能,比如优惠券、拼单、评价晒单,统一砍掉,在论文“后续展望”里写一句“可作为未来扩展方向”就够了。

这样设计的好处是,每一部分工作量都可控,同时数据的关联关系又足够复杂——用户、菜品、购物车、订单、订单明细五张表之间都有外键关系,写论文的时候ER图很丰满,答辩介绍的时候逻辑也清晰。

1.3 项目目录结构与代码组织

项目采用前后端分离的目录方式,分成backend(Django工程)和miniprogram(微信小程序工程)两个同级目录,这样两个端可以独立打包、独立部署。

online-ordering/ ├── backend/ │ ├── manage.py │ ├── requirements.txt │ ├── config/ # 项目配置 │ ├── apps/ │ │ ├── users/ # 用户模块 │ │ ├── dishes/ # 菜品与分类模块 │ │ ├── orders/ # 购物车与订单模块 │ │ └── common/ # 通用工具 │ └── static/ # 上传文件、静态资源 └── miniprogram/ ├── app.js ├── app.json ├── pages/ │ ├── index/ # 首页(菜品列表) │ ├── cart/ # 购物车 │ ├── orders/ # 订单列表 │ ├── order-detail/ # 订单详情 │ └── profile/ # 个人中心 └── utils/ └── request.js # 封装的网络请求

目录结构最大的原则是按业务模块切分,而不是按技术类型切分。很多同学喜欢把所有的views放一个文件、所有的models放一个文件,一旦功能多起来就会变成巨型文件,看着头疼改着也头疼。Django的app机制本来就是鼓励按业务拆分的,要充分利用框架的约定。

2. 后端核心实现:Django 模型与接口设计

后端侧的深度决定了这个毕设的评分上限。很多同学的毕设后台就是一套简单的增删改查——我的建议是,增删改查可以做,但业务状态流转一定要做对,这部分才是答辩时能和老师对话的深度所在。

2.1 数据库模型设计:五张表的关联关系

在线点餐系统的数据模型,我最终落在五张核心表上。设计的时候反复推敲过商品表和SKU(库存量单位)要不要拆开,后来考虑到毕设场景用不到规格属性,就简化成“菜品表 + 一个默认图片字段”。如果要做多规格,可以在菜品表下挂一个sku_set,但为了控制复杂度我放弃了。

这五张表分别是:

  • User(用户表):继承Django自带用户模型,新增openidavatar字段。openid是小程序用户的唯一标识,前端wx.login()拿到code后,后端通过微信接口换得,直接存数据库做唯一约束。
  • Category(分类表):字段就是namesort_order。排序很重要,首页菜品分类的展示顺序从sort_order取,而不是按ID。
  • Dish(菜品表)titledescriptionpriceimagecategory(外键)、is_available。价格字段用DecimalField(max_digits=8, decimal_places=2),这个类型在事务计算中能避免浮点数精度问题。is_available没上榜但非常关键——菜品下架是逻辑删除,不会影响历史订单的展示。
  • Order(订单表)order_no(订单号)、user(外键)、statustotal_amountremarkcreated_at。状态字段用SmallIntegerField加 choices 常量,而不是直接用字符串存,这样既保证可读性又能约束取值范围。
  • OrderItem(订单明细表)order(外键)、dish(外键)、price(下单时快照价格)、quantity。这里必须解释清楚:明细表里为什么要有dish外键,同时又要冗余price?因为菜品价格会变,但订单历史价格不能跟着变。

订单表与订单明细表是一对多关系,订单明细与菜品是一对一关系。这个设计保证了下单时的数据快照,后续菜品改价或删除,历史订单的账单依然准确。

2.2 基于 DRF 的接口设计与视图实现

后端API使用的是Django REST Framework。DRF对毕设项目最大的价值在于:序列化器帮你省了一大堆手写 JSON 序列化代码,而且它自带的Browsable API页面可以直接在浏览器里调试接口,写前端的时候非常方便。

接口设计上我遵循REST风格,按资源划分为:

POST /api/auth/login/ # 小程序登录,code换openid GET /api/categorys/ # 分类列表 GET /api/dishes/ # 菜品列表(支持分类过滤) GET /api/dishes/<id>/ # 菜品详情 POST /api/cart/ # 添加购物车 GET /api/cart/ # 获取购物车 PUT /api/cart/<id>/ # 修改购物车数量 DELETE /api/cart/<id>/ # 删除购物车条目 POST /api/orders/ # 创建订单 GET /api/orders/ # 我的订单列表 GET /api/orders/<id>/ # 订单详情

写视图的时候,特别注意了ModelViewSetAPIView的搭配使用。购物车、订单这类需要校验业务逻辑的接口,我选择用APIView手写逻辑,理由是有时候业务规则比增删改查的通用流程更复杂——比如下订单时要开启事务,把购物车数据搬入订单明细的同时清空购物车,这一步用ModelViewSet很难优雅表达。

下订单接口的核心逻辑是这个:

class OrderCreateView(APIView): permission_classes = [IsAuthenticated] def post(self, request): user = request.user # 基于购物车生成订单,必须用事务 with transaction.atomic(): cart_items = CartItem.objects.filter(user=user).select_related("dish") if not cart_items.exists(): return Response({"detail": "购物车为空"}, status=status.HTTP_400_BAD_REQUEST) order = Order.objects.create( user=user, order_no=generate_order_no(), status=Order.Status.PENDING, total_amount=sum([item.dish.price * item.quantity for item in cart_items]) ) for item in cart_items: OrderItem.objects.create( order=order, dish=item.dish, price=item.dish.price, quantity=item.quantity ) cart_items.delete() # 下单成功后清空购物车 return Response({"order_no": order.order_no}, status=status.HTTP_201_CREATED)

这里最关键的两个点是:transaction.atomic()保证购物车搬移过程的原子性,任何一个环节失败都不会产生半截订单;sum计算总价用的Decimal类型,避免浮点数精度问题。

我看过不少同题的毕设,下单逻辑是把整个购物车数据直接JSON序列化塞进订单的一个TextField里。这种做法前期省事,后期想要按菜品维度做数据统计就非常痛苦,而且清晰度远不如一对多关联表。如果目标不仅仅是“能交差”,还是建议用标准的关联表设计。

2.3 用户认证方案:微信登录与JWT

小程序端没有传统的账号密码登录流程,后端认证我用了JWT(JSON Web Token)。方案选的是djangorestframework-simplejwt,然后在它的基础上包装了一个微信登录接口,整个流程是:

  1. 小程序端调用wx.login()获取临时code
  2. 后端向微信服务器请求(https://api.weixin.qq.com/sns/jscode2session)换取openidsession_key
  3. 后端在User表里按openid查用户,查不到就注册新用户。
  4. RefreshToken.for_user(user)生成JWT返回给前端。
  5. 后续请求在小程序端把token放进请求头的Authorization: Bearer <token>
  6. 后端用IsAuthenticated校验身份。

这里要注意,小程序的code是临时凭证,5分钟有效,后端换取完openid之后不要存code,也不要直接信任前端传过来的openid——正确做法是后端拿code去微信接口换,不能让前端把openid直接传过来,否则任何人都可以伪造身份登录。

Django侧还需要把JWT认证加到REST Framework配置里:

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

需要匿名访问的接口(比如菜品列表),在视图上单独加permission_classes = [AllowAny]覆盖。

2.4 菜品图片上传与访问

菜品图片这块大多数毕设直接用URL链接填进去,省事,但我还是建议做一个本地上传接口,理由有二:一是答辩演示时如果网络不稳定,外部图片加载会非常慢;二是图片存在本地,能让你的系统看起来更完整、更像一个能独立部署的产品。

Django端做上传接口也不复杂,核心是配置MEDIA_URLMEDIA_ROOT,再在urls.py里加一行static路由。小程序端用wx.uploadFile上传临时路径,后端接收到文件后存到media/目录,返回存储的相对路径给前端拼接完整地址。

不过这里有个坑:Django默认的FileField存储文件名是原始文件名,中文名和特殊字符可能导致小程序端加载失败。我建议重写保存逻辑,统一按日期+随机串重命名:

def dish_image_upload_path(instance, filename): ext = filename.split('.')[-1] new_name = f"{uuid.uuid4().hex}.{ext}" return f"dishes/{datetime.now():%Y/%m}/{new_name}"

这种做法还能顺带解决目录过大的问题——按年月分目录,后续排查时也方便。

3. 前端核心实现:微信小程序页面与交互

小程序端是用户直接接触的部分,也是毕设演示时长最长的部分,UI的精致程度直接决定了答辩的第一印象。

3.1 页面架构与底部导航设计

小程序端规划了四个底部导航Tab:首页(点餐)、购物车、订单、个人中心。对应app.json里的tabBar配置。

这里有一个容易被坑的地方:tabBar的图标不允许使用网络图片,必须使用本地静态资源,而且图标文件大小不能超过40KB。网上很多教程用的示例图标都是png格式,但小程序的 tabBar 其实也支持svg,不过要注意兼容性。建议直接用字体图标转png,尺寸按81px设计。

首页是核心业务页面,布局采用左分类、右菜品的经典样式。左侧是滚动分类栏,右侧是用scroll-view包裹的菜品列表。这里有一个性能优化细节:如果在scroll-view里渲染几十个菜品图片,快速滑动时会出现明显的白屏闪烁。解决方案是用小程序提供的image组件的懒加载属性lazy-load,或者直接用wx:for配合wx:key减少重复渲染。

分类切换时右侧列表要做两种处理:如果只是切换分类,可以用scroll-viewscroll-into-view定位到对应分类区域;如果是需要整页刷新菜品,则直接重新请求接口。我采用后者,虽然多一次网络请求,但实现更简单、逻辑更稳定。

3.2 购物车数据的管理与同步策略

购物车是整个前端交互逻辑最复杂的部分,难点在于数据要能够在多个页面间共享同步。小程序中没有Vuex那样的全局Store,所以我们要自己设计一个轻量方案。

我采用的是本地缓存 + 接口同步的双层策略:

  • 购物车数据在本地缓存的键叫cart_items,数据结构是一个数组,每个元素是{dish_id, title, price, image, quantity}
  • 用户加购、减购时,同步更新本地缓存,同时调用后端购物车接口做持久化。
  • 请求失败时以本地缓存为准,下次进入小程序时再尝试同步。

这个策略的好处是,用户就算断网也能把菜加到购物车(体验上很流畅),不过下单操作必须保证网络畅通,因为后端要校验库存和价格。

加购操作的逻辑如下:

addToCart(dish) { const cart = wx.getStorageSync('cart_items') || []; const index = cart.findIndex(item => item.dish_id === dish.id); if (index > -1) { cart[index].quantity += 1; } else { cart.push({ dish_id: dish.id, title: dish.title, price: dish.price, image: dish.image, quantity: 1 }); } wx.setStorageSync('cart_items', cart); this.updateCartBadge(cart); // 更新 tabBar 购物车角标 this.syncCartToServer(cart); // 异步同步到后端 }

关键是updateCartBadge这个函数,用wx.setTabBarBadge设置购物车角标数字,让用户有明确的操作反馈。很多同学会漏掉这一步,导致用户加了东西但完全看不到反馈,体验很减分。

关于同步策略,我踩过一个坑:如果用户在短时间内连续快速点击加购,会出现多次重复的POST请求,后端可能把这些都当成独立购物车条目而不是累加。解决办法是加一个简单的防抖——每次加购后设置一个500毫秒的定时器,如果期间没有新的操作,才真正把购物车同步到服务器。

3.3 小程序端API请求的封装要点

网络请求这块,不建议在每个页面里直接写wx.request,一定要封装成统一的request工具函数,统一处理三件事:认证头的注入、错误码的统一识别、会话过期的自动处理。

// utils/request.js const BASE_URL = 'http://127.0.0.1:8000/api'; function request(path, method = 'GET', data = {}) { return new Promise((resolve, reject) => { const token = wx.getStorageSync('token'); wx.request({ url: `${BASE_URL}${path}`, method, data, header: { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '' }, success(res) { // 约定返回格式 { code, data, message } if (res.statusCode === 200) { resolve(res.data); } else if (res.statusCode === 401) { // token失效,重新登录 wx.removeStorageSync('token'); wx.navigateTo({ url: '/pages/login/login' }); reject(new Error('请先登录')); } else { wx.showToast({ title: res.data.message || '请求失败', icon: 'none' }); reject(new Error(res.data.message || '请求失败')); } }, fail(err) { wx.showToast({ title: '网络异常', icon: 'none' }); reject(err); } }); }); } module.exports = { request, BASE_URL };

有一个细节容易被忽略:在小程序开发工具里,http://127.0.0.1:8000可以正常请求,但是在真机预览时,这个地址指向的是手机本机,而不是你的电脑。真机调试时必须在开发者工具的“详情-本地设置”里勾选“不校验合法域名”,并且把BASE_URL改成你电脑的局域网IP,比如http://192.168.1.100:8000。这个“电脑能跑、手机不行”的问题,是每年毕设答辩现场最容易翻车的事故。

3.4 提交订单与支付逻辑的简化处理

真实点餐系统都有支付环节,但毕设项目通常不会真的对接微信支付——因为商户号申请和个人资质限制太多,很多同学根本走不完流程。我的替代方案是“货到付款”模式,也就是订单创建后状态直接是“待接单”,不需要真实资金流转。

这个取舍在论文里是这样写的:“考虑到演示环境和学生身份限制,系统采用先下单后支付的设计,支付模块可通过后续对接微信支付接口完成。” 这样既规避了资质问题,也体现了论文的完整性。

提交订单的页面从购物车进入,读取缓存的购物车数据,展示商品清单和总价,同时让用户填一个备注(比如“不要辣”“多加一份米饭”)。提交按钮触发POST /api/orders/,成功后清除本地购物车缓存,跳转到订单列表页。整个交互链路短,流程清晰,演示时也非常直观。

4. 联调、部署与疑难杂症排查实录

校园网环境、Windows/Mac混用、Python版本不一致……毕设开发中遇到的环境问题往往比业务代码的死板 bug 更折磨人。这一部分是我最想分享给后来者的内容。

4.1 从零配置 Django 开发环境

Django项目的环境配置,踩得最多的坑是Python版本和包版本的匹配。Python 3.12发布后,很多依赖包还没有及时适配,直接pip install django可能装不上最新版。我的建议是不要追求最新版本,用稳定组合

毕设开发的验证过组合:

软件推荐版本备注
Python3.10.x兼容性最好的版本
Django4.2.xLTS长期支持版
djangorestframework3.14.x稳定版
djangorestframework-simplejwt5.2.x需和DRF匹配
django-cors-headers4.x解决跨域问题

创建虚拟环境是必须的一步,这不是可有可无的规范,而是实实在在的保命措施:

python -m venv venv # Windows激活 venv\Scripts\activate # macOS/Linux激活 source venv/bin/activate pip install -r requirements.txt

装了django-cors-headers之后,必须在settings.py里加两处配置,否则小程序请求会报跨域错误。这是新手最容易漏的地方:

INSTALLED_APPS = [ ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] CORS_ALLOW_ALL_ORIGINS = True # 开发环境直接全开

开发环境无所谓的,但部署上线时CORS_ALLOW_ALL_ORIGINS一定要关掉,改成白名单,不然别人网站可以直接调用你的接口,还是有点吓人的。

4.2 购物车提交订单时“总和对不上”的问题

这个问题我调试了整整一个下午:购物车里明明显示的是58元,提交订单后后台算出的是57.8元,差了两毛钱。

排查之后发现,原因出在数据库的DecimalField和 Pythonfloat的转换上。我在前端把价格Number(dish.price)传给了后端,Django再把JSON数字转Decimal,中间经过了浮点运算,出现精度误差。

解决方案是:价格相关的参数永远不传数值,而是传字符串,或者后端以ID为准从数据库重新读取价格,不信任前端传来的任何价格字段。我在后端下单逻辑里直接改为从购物车关联的菜品表取出价格,前端传来的字段全部忽略。这个修改也符合电子商务系统的基本安全原则——客户端价格不可信。

4.3 微信小程序真机预览连不上Django

这个问题一句话概括就是“小程序的网络请求必须走HTTPS或者被标记为信任的域名”,但这只是表面。更实际的情况是,开发者在本地用python manage.py runserver 0.0.0.0:8000起服务,然后手机和电脑连同一个WiFi,小程序真机预览时请求局域网IP,然后报错request:fail

这个问题的排查顺序应该是:

  1. 在电脑上浏览器访问http://127.0.0.1:8000/api/dishes,确认服务正常运行。
  2. 在同一网络下的手机上访问http://电脑局域网IP:8000/api/dishes,确认防火墙不会阻断端口。这一步很关键,Windows的防火墙经常默认阻止Python进程访问局域网。
  3. 在微信开发者工具里勾选“详情 -> 本地设置 -> 不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”。
  4. 如果还是没有请求成功,打开电脑的“允许应用通过防火墙”,把Python的专用网络访问权限打开。

只要跑通一次真机联调,后面的开发就顺了。但要提醒的是,每次切换网络(比如从宿舍换到教学楼WiFi),电脑IP会变,小程序里的BASE_URL也要跟着改。这个我在开发中遇到了至少三次,后来直接写了一个配置页面来改地址,不用反复改代码。

4.4 常见问题速查表

这段做成了一个排查清单,实际开发中遇到的大部分问题都可以按图索骥:

现象可能原因解决方案
小程序请求报request:fail域名没配白名单 / 没有关闭域名校验 / 防火墙拦截勾选“不校验合法域名”,检查防火墙端口
Django启动后访问 404urlpatterns路径少了一层 /ALLOWED_HOSTS没配置检查ALLOWED_HOSTS = ['*'],检查URL路由
图片上传成功后小程序显示不出来图片路径是相对路径,拼接URL出错前端保存完整MEDIA_URL + 文件路径
购物车数量为负数前端连续点击“减少”按钮加防抖或判断quantity <= 1时直接删除条目
订单状态一直不变商家端没有处理接单逻辑在Django Admin自带的订单模型里手动修改状态字段
登录报code2Session错误 400小程序的 AppSecret 配置错误或已重置登录微信公众平台重新获取 AppSecret
Python 3.12 下mysqlclient安装失败没有合适的wheel包换上PyMySQL,在__init__.pypymysql.install_as_MySQLdb()
列表滑动卡顿页面渲染数据量过大 / 图片未懒加载使用lazy-load,给wx:forwx:key

4.5 本地开发到部署上线的完整流程

如果导师要求你答辩后把系统部署到云服务器上(这个情况还挺常见的),部署流程也要提前演练一遍。我的部署方案是:Nginx + uWSGI + Django + MySQL,小程序端仍然通过开发者工具加载,不涉及静态资源托管。

部署的关键步骤:

# 1. 服务器安装依赖 sudo apt update sudo apt install python3-pip python3-venv nginx mysql-server pip install uwsgi # 2. 拉取代码并安装依赖 git clone <你的仓库地址> cd online-ordering/backend python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # 3. 收集静态文件和数据库迁移 python manage.py collectstatic --noinput python manage.py migrate python manage.py createsuperuser # 4. 配uWSGI uwsgi --http :8000 --module config.wsgi --master --processes 4 --threads 2 # 5. 配Nginx反向代理,/api和/media/转发到8000端口

Nginx的配置文件核心就是反代,具体来说是把静态文件和/media/路径交给Nginx直接处理,/api/开头的请求转发给uWSGI。

部署时还有几个坑:DEBUG = False之后Django不会自动处理静态文件,需要collectstaticALLOWED_HOSTS必须改成你的域名或服务器IP;上传的媒体文件建议单独建一个目录并做软链接,否则重新部署代码时容易丢失用户上传的图片。部署完成后记得用systemctl或者supervisor守护uWSGI进程,不然服务器一断开SSH,整个后端服务就跟着挂了。

5. 复盘:这个毕设项目能扩展出什么

做完这套在线点餐系统,再回头看这个题目,我觉得它最值得做的地方不是“完成”,而是“留白”——技术栈的每一部分都有进一步深入的空间,论文的每一章都能引出一个值得探讨的问题。

如果还想在答辩前再拔高一点,有几个方向我认为比较适合短期扩展:

一是把菜品推荐加进来。基于用户的历史订单,计算菜品共现频率,推荐逻辑不复杂,但能展示你懂一点协同过滤算法的知识。

二是加入商家端的Web管理界面。不用多精美,只需在Vue或React里做一套菜品和订单的管理页面,替换掉Django Admin的默认页面,整套系统的完整性会立刻提升一个档次。注意这里要加一层角色权限,不然用户也能登录管理后台乱改。

三是订单状态的消息推送。使用小程序的订阅消息功能,用户下单后推送“商家已接单”的消息通知。这个很实用,也是小程序原生能力的一个亮点。

开发这套毕设的过程中我收获最大的不是Django的某一个功能,也不是小程序组件的某个API,而是真正理解了一个业务系统从需求分析到架构设计再到最终落地的完整闭环。它能让你在面试的时候聊出“订单金额为什么用Decimal而不是float”“购物车数据为什么要本地缓存和服务端同步双写”“为什么下单要放在事务里”这些有深度的问题,这些都比“我会用Django写接口”更有说服力。

最后分享一个小技巧:项目代码里一定要写满注释,尤其是那些你当时琢磨了很久才想通的地方。答辩前一个月你可能还会看得懂,等到答辩前一周再打开自己写的代码,如果没有注释,你会怀疑这是不是自己写的。

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

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

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

立即咨询