做民宿预订这个项目之前,我心里其实是有过犹豫的。市面上成熟的民宿预订方案一抓一大把,直接套个SaaS或者开源的民宿系统改改就行了,为什么还要拿Python + Django这套技术栈从头写一套“小程序端 + PC Web端 + 手机浏览器端”三端通用的民宿预订系统?后来真正动手之后我明白了:如果只是应付“能下单、能收款”,那确实没必要折腾。但民宿老板真正要的不只是一个订房页面,而是一套能把房态、订单、价格日历、客户管理全部串起来、并且随时能在手机和电脑上操作的管理工具。Django的ORM和Admin体系加上小程序端灵活的交互,恰好可以把这个“既要给客人用、又要给自己管”的需求做得比较舒服。
这篇博文主要针对有Python基础、想把Django和小程序串成一个完整闭环项目的开发者。我会从系统架构、数据模型设计、Django后端接口实现、小程序端对接、PC管理端要点,再到真正的部署上线和踩坑排查,把整个项目的关键设计决策和实操细节都摊开来讲。内容偏实战,项目里直接能落地的代码思路和配置都会给到,至于具体业务细节,可以根据你自己接手的民宿项目灵活调整。
1. 一套系统三端跑:民宿预订项目的整体架构与数据流设计
1.1 为什么这个小程序系统要同时做PC Web端
一开始的需求其实很单纯,民宿老板说:“我要一个小程序,客人能看房、订房、付钱。”听起来很简单,但等你把需求往细了挖,就会发现单做一个小程序根本不够用。
客人端确实是小程序最方便,微信里扫码就能进,不用下载App,也不用注册账号。但民宿老板自己呢?他每天要改房价、关房态、查订单、看哪个房间今天该打扫了。这些操作如果都挤在小程序里做,要么把管理功能堆在同一个前端项目里导致小程序包体积膨胀、审核也麻烦,要么老板只能天天抱着手机在小程序后台里戳来戳去,体验很差。
所以这套系统最终定了三端:
- 小程序端:给C端客人使用,负责房源展示、房态日历、下单支付、订单查询、退款申请;
- PC Web管理端:给民宿老板和运营人员使用,负责房源管理、价格日历批量设置、订单处理、经营数据统计;
- 手机H5端:给客人和管理员在手机浏览器上应急用的轻量版本,复用同一套API。
三个端共用同一个Django后端,数据完全打通。这样一来,老板在PC上设置好某间房下周一到周三的价格,小程序端客人刷新立即生效;客人在小程序上提交了订单,PC后台马上能看到待确认订单,还能推送提醒。这套“一后端多前端”的结构,是这类业务系统的核心骨架。
1.2 三端共用的核心数据模型
民宿预订业务的本质,就是“房态、价格、订单”三张表之间的状态博弈。这里我把最核心的数据模型列出来,这几个模型是所有业务接口的基石:
code复制House(房源模型)
- 名称、封面图、轮播图、地址、描述
- 房型类型(整栋/单间)、面积、可住人数
- 基础设施:无线网、空调、厨房、停车位等
- 基础价格(平时价)、押金、清洁费
- 上架状态、审核状态
- owner(关联民宿主账号)
Room(房间/房源库存单元)
- 归属House
- 房号、房间描述、最大入住人数
- 默认价格(用于价格日历未设置时的兜底)
PriceCalendar(价格日历)
- 关联Room
- 日期、当日价格、当日房态(可订/已订/停售/打扫中)
- 是否被手动锁房
- unique约束:(room_id, date)
Order(订单模型)
- 订单号(业务编号,如BZ+日期+随机串)
- 关联Room、下单用户
- 入住日期、离店日期、入住人数
- 款项明细:房费总额、清洁费、押金、优惠金额、实付金额
- 订单状态:待支付 / 待确认 / 已确认 / 已入住 / 已离店 / 已取消 / 退款中 / 已退款
- 联系人姓名、手机号
- 支付信息:微信支付单号、支付时间
- created_at、updated_at
User(用户模型)
- 唯一标识(小程序openid绑定)
- 昵称、头像、手机号
- 用户角色(guest/owner/admin)
这几个模型看起来不复杂,但表关系和数据约束一旦设计错了,后面会非常痛苦。尤其是PriceCalendar这个表,它承担了“价格 + 房态”双重职责,是整个系统的状态源头。不要用“开始日期-结束日期”区间段来存价格,那样改中间某一天的价格时你会崩溃。按天存储一行,虽然数据量会大一些,但查询和修改都极其简单清晰,配合Django的unique_together约束,能从根本上避免重复数据。
1.3 三端接口调用的数据流逻辑
Django后端只提供RESTful API,三端前端都走HTTP请求。数据流大概是这样的:
- 客人打开小程序,先调用
wx.login()拿到code,后端用code换openid,在User表里匹配或创建用户,签发自定义登录态; - 客人浏览房源列表,小程序调用
GET /api/houses/?check_in=2025-06-01&check_out=2025-06-03接口,后端根据入住日期和离店日期,在PriceCalendar表里过滤出期间内所有可订且价格符合条件的房间; - 客人提交订单,后端执行“创建订单 + 锁定房态 + 预占库存”的一系列事务操作,返回订单号和支付参数;
- 客人调用微信支付,支付成功后微信服务器异步回调Django接口,后端验签、更新订单状态、确认房态锁定;
- 老板在PC管理端登录后,调用
GET /api/admin/orders接口查询所有订单,并进行接单、改价、退款等操作。
这里最关键的思路是:前端只负责展示和收集操作意图,所有状态变更和业务校验都放在后端完成。比如小程序端看起来“有房”,但提交订单时房间可能已经被别人占了,所以后端必须在下单时重新校验房态,而不是相信前端传过来的数据。这也是为什么接口设计比页面设计更重要的原因。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Django后端:从项目骨架到民宿业务模块落地
2.1 项目初始化与App拆分的考量
Django项目创建本身没什么好讲的,django-admin startproject一把梭。但App的拆分方式,我建议按业务域拆,而不是按技术层拆。
我当时是这样拆的:
code复制houses_app:房源与房态管理
orders_app:订单与支付
users_app:用户与登录认证
payments_app:支付回调与退款
statistics_app:经营统计
common_app:公共工具、异常处理、分页封装
这样拆分的好处是,每个App的业务边界非常清晰,后面做权限控制、写单元测试、甚至将来把某个模块拆成微服务,都能平滑过渡。如果你图省事把所有东西都塞进一个App,项目一开始写起来确实快,但等业务复杂到一定程度,一个models.py文件几千行,你会连想改一个字段都要翻半天。
创建App时要顺手解决几个基础问题:
第一,自定义用户模型。官方默认的User模型没有openid字段,而且扩展起来麻烦。所以要在项目启动后第一时间在users_app里创建自定义用户模型:
python复制class User(AbstractUser):
openid = models.CharField(max_length=128, unique=True, null=True, blank=True)
phone = models.CharField(max_length=20, null=True, blank=True)
avatar = models.URLField(null=True, blank=True)
nickname = models.CharField(max_length=64, null=True, blank=True)
role = models.CharField(max_length=20, choices=(
('guest', '客人'), ('owner', '民宿主'), ('admin', '管理员')
), default='guest')
并且记得在settin
