前后帮人做过好几个家政类的管理系统自己也从零折腾过完整的“Python django flask家政服务管理系统”。这活儿看着简单实际踩进去才发现里面全是细节客户下单、阿姨接单、派单冲突、服务时长、财务结算、评价管理每一块都得理顺。网上讲Django或Flask框架的教程很多但专门系统讲家政平台怎么从需求拆解到落地的文章不多所以我把自己的完整思路和踩坑过程整理出来给正准备做类似项目的朋友做个参考——不管你是初学Python想找个完整项目练手还是给家政公司做外包系统这篇文章的内容都能直接复用。我在选型时最终用的是Django但中间也认真对比过Flask甚至用Flask写过一版原型。这篇文章会把两个框架的取舍逻辑、数据表怎么设计、核心流程的代码怎么落地、部署上线怎么配置讲清楚最后再把我实际踩过的坑一条条列出来。内容偏工程实践不是教科书式的概念讲解你可以把它当成一份完整的项目复盘来看。1. 先别急着写代码家政管理系统的需求拆解很多人拿到“家政服务管理系统”这种题目第一反应是建几个表、写几个页面就完事。但我做了几个项目之后越来越确信家政系统的难点不在技术而在需求——你连业务都没理顺代码写得再多也是空中楼阁。1.1 角色与权限家政平台的用户到底有几种家政服务管理系统最容易被忽略的一个点就是角色设计。它不是简单的“用户管理员”两层结构至少得拆出四类角色管理员/运营人员管理阿姨信息、审核资质、派单、处理投诉、查看经营报表客户注册登录、浏览服务项目、下单、支付、评价、查看服务记录家政服务人员阿姨/保洁/护理师查看订单、接单/抢单、开始服务、完成服务、查看自己的结算收入财务/对账人员可以跟管理员合并但大一点的中介公司会分开核对订单金额、处理退款、给阿姨结算工资这四类角色对同一笔订单的关注点完全不同。客户看的是“我的订单到哪一步了”阿姨看的是“我今天去哪家干活”管理员看的是“整体履约情况”。所以做权限设计时不能只靠django自带的is_staff字段死磕而要在用户模型上拓展角色字段或者直接用独立的用户类型表来区分。我的做法是自定义一个继承AbstractUser的User模型加一个role字段取值是customer、worker、admin三种。后续所有接口、页面、菜单都根据role做不同渲染。这样设计有个好处——等系统跑起来了你还能灵活扩角色比如加个“门店经理”或者“客服”不用动底层的用户表。1.2 核心业务链路从下单到结算的完整闭环家政系统的核心链路我习惯画成一条线客户选择服务项目并预约时间 → 系统匹配可用的阿姨 → 阿姨接单或管理员手动派单 → 上门服务 → 客户确认完成 → 评价 → 财务结算。这条链上有几个关键分支预约时间冲突处理。一个阿姨同一时间只能接一个单系统必须在派单时校验阿姨的时间表否则会出现“一个阿姨同时出现在两个客户家”的尴尬情况。订单取消和改期。客户可能提前几小时取消阿姨也可能临时请假。订单状态不能只做单向流转必须设计成状态机允许特定条件下回退或分支。结算体系。家政公司通常不是简单地把客户付款全额给阿姨而是按比例抽成或者按每单固定抽成。结算单需要关联订单、客户付款、阿姨佣金三块数据。这些分支看起来零碎但每一个都影响表结构设计。如果一开始不把它们考虑进去后面返工的代价非常大。1.3 容易被忽略的隐藏需求除了主链路还有几个需求是家政公司老板一定会提、但技术文档里很少写的阿姨上下户记录。客户可能会评价“阿姨迟到了”“干活仔细”这些评价需要跟具体订单绑定沉淀成阿姨的服务档案。服务地理范围。家政公司通常只服务特定城区下单时要校验客户地址是否在服务范围内。这个用Django的模型字段可以存经纬度或区域标记派单时做一次过滤。经营数据看板。老板要看的不是“有多少个订单”而是“本周营收多少”“哪个服务项目卖得最好”“哪个阿姨好评率最低”。这些统计需求决定了你的订单表不能只存一条流水还要冗余一些用于统计的字段比如订单完成时间、金额、项目分类。我现在接这类项目第一步永远是拉表格把需求列给客户确认而不是先问用什么框架。框架只是实现工具业务逻辑才是家政系统的灵魂。2. Django与Flask的取舍我的选型复盘项目标题里同时出现了django和flask两个词这两个框架确实都能做家政系统。我也在拿到这个项目时认真对比过最后选了Django原因以及对比过程分享给大家。2.1 为什么我最终选了Django家政服务管理系统本质上是一个数据密集型业务系统它有大量表单、列表页、权限管理、数据处理需求。Django在这种场景下有几点天然优势第一自带的Admin后台能省掉一大半的运营页面开发时间。关于家政系统的每一项基础数据——服务项目、阿姨资料、行政区划、价格标准——放在Django Admin里面管理非常顺手。虽然很多人觉得Admin丑、不够灵活但给家政公司做内部系统Admin简直是快速搭建后台的神器。你可以通过自定义ModelAdmin去控制列表展示哪些字段、哪些字段可搜索、哪些字段可过滤几乎不用写代码。第二Django ORM自带迁移机制。家政系统的表结构大概率会在开发过程中调整——今天加个“是否带证上岗”字段明天加个“服务时长”字段——用makemigrations和migrate两条命令就能平滑更新数据库不用手工维护SQL脚本。第三用户认证体系开箱即用。Django有内置的auth应用认证、Session、登录状态管理都现成我们只需要扩展自定义字段即可。2.2 Flask在什么情况下值得用不是刻意贬低Flask。我早期也用过Flask做过原型——把订单列表、服务项目接口用Flask写出来非常快代码量看起来也比Django少。如果你满足以下条件Flask也完全可以系统核心是接口服务不需要复杂的模板渲染前后端分离前端全部走API用户量非常小比如只给一个小门店用不用复杂权限你自己很熟悉Flask-SQLAlchemy、Flask-Login等扩展组合心里有数但Flask的坑在于——“自由”意味着“自己做决定”。没有自带Admin、没有内置ORM迁移管理、没有用户认证实现这些都得靠第三方扩展拼接搭出来的项目就像积木搭起来的前期快后期重构成本高。家政系统又要管用户、又要管订单、又要管统计报表这种系统用Django开发效率还是高出一截。2.3 给不同人群的选型建议如果你是学生做课设/毕设选Django。因为家政管理系统的评分点在“功能完整性”和“业务合理性”上Django的Admin后台可以直接截图凑功能清单自带ORM写查询也不容易出错。如果你是给家政公司做外包选Django。外包项目最怕的是改需求Django的迁移机制和后台定制能力让你面对“加个字段”“加个页面”的需求时更从容。如果你是纯练习Python Web开发想熟悉框架差异两个都可以试先拿Flask写个最小原型感受一下手写一切的费劲再用Django把同样的功能实现一遍对比会很直观。我不建议新手在同一个项目里同时混用Django和Flask——那会让项目变成一个四不像。选一条路走到底。3. 数据模型设计把阿姨、订单和账单的关系理顺数据模型是家政系统的地基。我见过太多项目倒在这上面——表结构设计不合理写业务逻辑的时候发现这个字段查不出来、那个关系炸掉了。以下表结构是我在几个家政项目里沉淀出来的核心模型可以直接抄。3.1 用户与档案扩展Django自带的Userfrom django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): ROLE_CHOICES ( (customer, 客户), (worker, 服务人员), (admin, 管理员), ) role models.CharField(max_length20, choicesROLE_CHOICES, verbose_name角色) phone models.CharField(max_length20, uniqueTrue, verbose_name手机号) avatar models.ImageField(upload_toavatars/, blankTrue, verbose_name头像) class Meta: verbose_name 用户 verbose_name_plural 用户 def __str__(self): return f{self.username}-{self.get_role_display()}这里有两个关键点。一个是phone字段的唯一约束很多家政系统用手机号登录而不是用户名加唯一索引能防止重复注册。一个是角色字段务必保留扩展空间不要用布尔字段is_worker要用带选择的字符字段后面扩展角色时不需要改表结构。服务人员阿姨的信息比客户复杂得多需要单独建档案表class WorkerProfile(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE, related_nameworker_profile, verbose_name关联用户) service_categories models.ManyToManyField(ServiceCategory, verbose_name擅长服务项目) years_of_experience models.IntegerField(default0, verbose_name从业年限) id_card models.CharField(max_length30, blankTrue, verbose_name身份证号) introduction models.TextField(blankTrue, verbose_name简介) is_verified models.BooleanField(defaultFalse, verbose_name是否审核通过) rating models.FloatField(default5.0, verbose_name综合评分) class Meta: verbose_name 服务人员档案 verbose_name_plural 服务人员档案is_verified这个字段非常重要。家政公司对阿姨的身份证、健康证、技能证书有审核流程新注册的阿姨不能直接接单必须管理员在后台审核通过后才能进入接单池。这个字段既是一个权限开关也是一个运营状态。3.2 服务项目与订单核心的业务数据表服务项目表很直观但要注意跟“时长计价”结合class ServiceCategory(models.Model): name models.CharField(max_length50, verbose_name服务项目名称) description models.TextField(blankTrue, verbose_name服务描述) price_per_hour models.DecimalField(max_digits10, decimal_places2, verbose_name每小时价格) min_hours models.IntegerField(default2, verbose_name最低预约小时数) is_active models.BooleanField(defaultTrue, verbose_name是否上架) class Meta: verbose_name 服务项目 verbose_name_plural 服务项目 def __str__(self): return self.name订单表是家政系统中字段最多的表我把关键字段列出来class Order(models.Model): STATUS_CHOICES ( (pending, 待接单), (assigned, 已指派), (in_progress, 服务中), (completed, 已完成), (cancelled, 已取消), (settled, 已结算), ) customer models.ForeignKey(User, on_deletemodels.PROTECT, related_namecustomer_orders, verbose_name客户) worker models.ForeignKey(User, on_deletemodels.PROTECT, related_nameworker_orders, nullTrue, blankTrue, verbose_name服务人员) category models.ForeignKey(ServiceCategory, on_deletemodels.PROTECT, verbose_name服务项目) address models.CharField(max_length255, verbose_name服务地址) service_datetime models.DateTimeField(verbose_name服务开始时间) duration_hours models.IntegerField(default2, verbose_name服务时长(小时)) amount models.DecimalField(max_digits10, decimal_places2, verbose_name订单金额) status models.CharField(max_length20, choicesSTATUS_CHOICES, defaultpending, verbose_name订单状态) remark models.TextField(blankTrue, verbose_name客户备注) created_at models.DateTimeField(auto_now_addTrue, verbose_name下单时间) class Meta: verbose_name 订单 verbose_name_plural 订单 ordering [-created_at] indexes [ models.Index(fields[status]), models.Index(fields[service_datetime]), ]几个关键点说明一下on_deletemodels.PROTECT用于关联用户和服务人员——订单一旦产生关联的用户不允许被直接删除防止历史数据断裂。这个选择在真实业务中非常重要。amount字段直接冗余在订单表里。它的值可以通过category.price_per_hour * duration_hours算出来但统计营收、导出报表时每次都实时计算太浪费资源冗余字段用空间换时间。订单表和用户表之间有两个外键——customer和worker都用related_name区分。这个写法新手容易搞混一个User可以拥有两种订单身份必须起不同的related_name。索引的添加是Django ORM最被低估的功能之一。订单表按status和service_datetime做筛选的频率极高不加索引会让查询速度随数据量增长直线下降。数据库索引要照型号需求针对性加别每个字段都建而是建在真正会被频繁where的字段上。3.3 派单时间冲突校验一张表解决一个阿姨在同一个服务时间段只能存在一个有效订单这个约束怎么实现直观想法是在代码里判断但我更推荐单独建一个时间占用表让这层关系清晰可见class WorkerSchedule(models.Model): worker models.ForeignKey(User, on_deletemodels.CASCADE, related_nameschedules, verbose_name服务人员) order models.OneToOneField(Order, on_deletemodels.CASCADE, verbose_name关联订单) start_time models.DateTimeField(verbose_name开始时间) end_time models.DateTimeField(verbose_name结束时间) class Meta: verbose_name 服务人员时间表 verbose_name_plural 服务人员时间表派单时查询这张表判断这个工人的时间片段是否被占用def is_worker_available(worker_id, start_time, end_time): conflict WorkerSchedule.objects.filter( worker_idworker_id, start_time__ltend_time, end_time__gtstart_time, ) return not conflict.exists()这个判断用的是区间重叠检测逻辑——两组时间段[start1, end1]和[start2, end2]重叠的充要条件是start1 end2 and end1 start2。一次查询就能判断性能很好逻辑也简单。这个需求如果在设计表结构时没想清楚等阿姨的订单量起来后会出现严重的派单冲突。我建议从第一天就把这张表带上。3.4 评价与结算离用户近、离钱也近评价表容易设计就是订单关联、评分和文字内容class Evaluation(models.Model): order models.OneToOneField(Order, on_deletemodels.CASCADE, related_nameevaluation, verbose_name关联订单) rating models.PositiveIntegerField(verbose_name评分1-5) comment models.TextField(blankTrue, verbose_name评价内容) created_at models.DateTimeField(auto_now_addTrue, verbose_name评价时间) class Meta: verbose_name 服务评价 verbose_name_plural 服务评价结算表则是连接客户付款和阿姨收入的桥梁。家政公司的抽成模式我一般在表里用commission_rate字段记录这样即使佣金比例调整了历史结算单仍然能算出当时阿姨该拿多少钱class Settlement(models.Model): order models.OneToOneField(Order, on_deletemodels.CASCADE, verbose_name关联订单) worker models.ForeignKey(User, on_deletemodels.PROTECT, related_namesettlements, verbose_name服务人员) order_amount models.DecimalField(max_digits10, decimal_places2, verbose_name订单金额) commission_rate models.DecimalField(max_digits5, decimal_places2, default0.20, verbose_name平台抽成比例) worker_income models.DecimalField(max_digits10, decimal_places2, verbose_name阿姨所得) status models.CharField(max_length20, choices((pending, 待结算), (paid, 已结算)), defaultpending, verbose_name结算状态) class Meta: verbose_name 结算单 verbose_name_plural 结算单经验提示结算单里的order_amount、worker_income这些金额字段必须存“当时的值”不能在页面里实时去算——因为订单金额可能因为退款或优惠调整而变化历史结算如果跟着变财务对账必然对不上。这是我踩过好几次的坑牢记凡是涉及钱的字段宁可冗余也要在落库时把当时的金额固定下来。4. 核心业务流程的代码落地从下单到结算表结构设计好了接下来就是把业务流程用代码串起来。这一部分我挑几个关键的场景讲直接给可以落地的方案。4.1 多角色登录与权限控制Django自带的login_required装饰器只认登录状态不认角色所以需要自己封装。from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied def role_required(*allowed_roles): def decorator(view_func): login_required def _wrapper(request, *args, **kwargs): if request.user.role not in allowed_roles: raise PermissionDenied return view_func(request, *args, **kwargs) return _wrapper return decorator # 使用示例 role_required(customer) def customer_dashboard(request): orders Order.objects.filter(customerrequest.user) # ...注意一个细节Django的raise PermissionDenied需要配合自定义的403模板默认的403页面很丑。我之前项目里加了403页面后用户体验好很多权限被拒时至少有个友好的提示和返回按钮。4.2 客户提交订单与自动算价一个家政系统最频繁的操作就是客户下单。前端页面展示服务项目、选择时间、填地址后端接收后自动计算金额并创建订单def create_order(request, category_id): if request.method POST: category ServiceCategory.objects.get(pkcategory_id) duration int(request.POST.get(duration_hours)) if duration category.min_hours: messages.error(request, 最少需预约{}小时.format(category.min_hours)) return redirect(service_detail, category_idcategory_id) amount category.price_per_hour * duration order Order.objects.create( customerrequest.user, categorycategory, addressrequest.POST[address], service_datetimerequest.POST[service_datetime], duration_hoursduration, amountamount, statuspending, ) messages.success(request, 下单成功等待分配服务人员) return redirect(order_detail, order_idorder.id)防并发资源竞争问题在下单流程里尤其重要。如果同一个服务时间被两个客户同时下单而系统先创建Order再检查WorkerSchedule会出现订单创建成功但派单时发现阿姨没时间的矛盾。我的建议是客户下单时只创建pending状态订单并锁定服务时间字段派单动作单独走一个函数并且用事务包裹from django.db import transaction transaction.atomic def assign_worker(order_id, worker_id): order Order.objects.select_for_update().get(pkorder_id) start_time order.service_datetime end_time order.service_datetime timedelta(hoursorder.duration_hours) if not is_worker_available(worker_id, start_time, end_time): raise Exception(该服务人员在此时间段已有订单) order.worker_id worker_id order.status assigned order.save() WorkerSchedule.objects.create( worker_idworker_id, orderorder, start_timestart_time, end_timeend_time, )select_for_update()在事务里对订单行加了行级锁能防止两个管理员同时派同一个订单导致状态错乱。这个知识点在单用户开发时不太显眼一旦上真实生产环境就会意识到它的重要性。4.3 订单状态的流转控制状态机这个概念听起来高级落地其实就是一句话写代码的时候明确每个状态允许迁移到哪些状态。我给订单状态加了映射表ALLOWED_TRANSITIONS { pending: (assigned, cancelled), assigned: (in_progress, cancelled), in_progress: (completed, cancelled), completed: (settled,), cancelled: (), settled: (), } def transition_order(order, new_status): if new_status not in ALLOWED_TRANSITIONS.get(order.status, ()): raise ValueError(f不允许从{order.status}流转到{new_status}) order.status new_status order.save()这样做的好处非常明显杜绝了“取消已完成订单”“结算未完成订单”这类业务逻辑漏洞。代码审查时一眼就能看清状态流转的所有路径运营人员再怎么乱点也不会把数据搞坏。4.4 定制Django Admin后台家政系统当然需要后台管理但我不想为每一个后台页面写一套模板。Django Admin的定制能力刚好够用。admin.register(Order) class OrderAdmin(admin.ModelAdmin): list_display [id, customer, worker, category, service_datetime, amount, status] list_filter [status, category] search_fields [customer__username, customer__phone, worker__username, address] date_hierarchy service_datetime list_editable [status] actions [mark_completed] def mark_completed(self, request, queryset): queryset.update(statuscompleted) mark_completed.short_description 标记所选订单为已完成几点说明search_fields里用双下划线去搜关联表字段比如customer__phone是搜客户手机号这是Django ORM关联查询在Admin中的典型用法。list_editable能直接在列表页下拉改状态运营操作效率极高。但注意它跟list_display里的字段不能重复否则Django报错。date_hierarchy不能随便用必须配合真实存在的日期类型字段对service_datetime这种时间字段做日期层级筛选非常顺手。4.5 通知阿姨接单的最简方案真正上线时你大概率还要给阿姨发短信或微信通知。但在开发阶段最务实的方案是“站内消息列表刷新”。我建了一个简单的通知模型class Notification(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE, related_namenotifications, verbose_name接收人) content models.CharField(max_length255, verbose_name通知内容) is_read models.BooleanField(defaultFalse, verbose_name是否已读) created_at models.DateTimeField(auto_now_addTrue, verbose_name创建时间)派单成功后写一条通知阿姨登录后打开通知列表就能看到新订单。这个方案不需要任何中间件先把流程串通以后要接短信或WebSocket推送再往上加层也非常方便。实际上模块化的设计就是让人能按需替换的通知这一层做得简单后面升级空间反而更大。5. 开发期的坑时区、状态流转与Admin定制的教训前面讲的是“应该怎么做”这一节讲讲我实际踩过的坑全是生产环境下真实发生过的问题希望帮你避开。5.1 时区问题导致家政订单时间错乱这是家政系统开发中最隐蔽也最容易翻车的坑。Django默认开启了时区支持USE_TZ True数据库里存的是UTC时间而你在中国显示的应该是北京时间。问题在于——如果模板里直接用order.service_datetime输出的往往是UTC时间比真实时间少了8个小时。我当时遇到的场景是客户预约了下午3点保洁系统后台显示预约时间是上午7点客户来投诉系统有问题。排查了半天才发现是时区渲染的锅。解决方案在settings.py设置TIME_ZONE Asia/ShanghaiUSE_TZ True。USE_TZTrue意味着Django内部统一用UTC存储时间只有输出时才转换为当地时区这样处理跨时区用户最安全。模板渲染时Django会自动把UTC时间转换为TIME_ZONE指定的时区不需要手动转换。但要注意如果你在代码里手动调用datetime.now()得到的是UTC时间必须改用django.utils.timezone.now()。很多新手在订单创建时间上踩这个坑就是因为用了系统的datetime。from django.utils import timezone now timezone.now() # 正确 # now datetime.datetime.now() # 错误得到的是本地时间但Django统一认为它是UTC5.2 事务并发与状态更新的原子性我之前在一个家政项目上遇到过一个问题两个管理员几乎同时给同一个订单派单结果系统的订单状态一会儿是“已指派给A阿姨”一会儿是“已指派给B阿姨”最后数据表里worker字段被B覆盖了但A阿姨那边已经看到接单通知了。这是典型的并发写问题。解决方案就是前面提到的select_for_update()在事务中锁定该订单行让后续写操作等待前一个事务释放锁。另一个安全操作是条件更新避免覆盖别人的修改updated Order.objects.filter(pkorder_id, statuspending).update(statusassigned, worker_idworker_id) if updated 0: return {success: False, message: 订单状态已变化请刷新后重试}这种“乐观锁”式的写法在单管理员的小型系统里就够用了代码更简单也不容易死锁。5.3 Django Admin的中文搜索与性能问题如果后台订单量上到几万条Admin的搜索和列表加载会明显变慢。这里有几个优化点search_fields里如果带icontains子查询Django会生成LIKE %xxx%的SQL这种模糊查询不会走索引。如果订单量巨大务必配合使用全文检索方案或者给常用搜索字段单独加索引并接受一定程度的精确匹配替代模糊匹配。list_display里尽量别放关联对象的__str__方法因为每显示一行都会触发一次额外的SQL查询获取关联表数据。用select_related提前把关联数据查出来class OrderAdmin(admin.ModelAdmin): def get_queryset(self, request): qs super().get_queryset(request) return qs.select_related(customer, worker, category)不要小看这个优化数据量上来后一页20条订单的列表请求时间可能从几秒降到几百毫秒。5.4 静态文件与图片上传路径家政系统一定会有图片上传的需求——阿姨传身份证照片、客户传服务图片、用户传头像。Django开发环境下文件上传是正常的但部署到生产环境后很多人会碰到“上传成功但页面加载不出来”的问题。原因在于Django的MEDIA_URL和MEDIA_ROOT没配对或者Nginx没有配置静态文件路由。我在settings.py这样配置import os BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media)开发环境的URL路由也要加上一段from django.conf import settings from django.conf.urls.static import static urlpatterns [ # ...你的路由 ] urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)只加MEDIA_URL不加MEDIA_ROOT是最常见的错误——数据库存的地址是对的但文件根本不存在于服务器路径上。这个坑碰到一次就长记性了。6. 部署上线与后续演进Gunicorn、Nginx与并发优化开发完成后要部署。家政公司一般没有专职运维所以部署方案要简洁可靠不能太复杂。我推荐“Gunicorn Nginx PostgreSQL/MySQL”的组合这是一套久经考验的Python Web部署方案。6.1 环境准备与依赖管理Python项目的依赖管理我强烈建议用虚拟环境加requirements.txt锁定版本python3 -m venv venv source venv/bin/activate pip install -r requirements.txtrequirements.txt从当前环境导出pip freeze requirements.txt生产环境上不要用SQLite家政系统虽然量不大但SQLite并发写能力差订单写入频繁时容易锁库。我一般用MySQL或PostgreSQL。Django连接MySQL需要装mysqlclient连接PostgreSQL需要装psycopg2-binary。6.2 Gunicorn启动与Nginx反向代理采集静态文件到指定目录python manage.py collectstatic --noinput然后用Gunicorn启动gunicorn 家政项目.wsgi:application --bind 127.0.0.1:8000 --workers 3Nginx配置做反向代理和静态文件服务server { listen 80; server_name yourdomain.com; location /static/ { alias /path/to/staticfiles/; } location /media/ { alias /path/to/media/; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }部署中最容易忽略的一个参数是ALLOWED_HOSTS。线上运行后如果忘记在settings.py里配置域名Django会拒绝请求并返回400错误。排查方式很简单看一眼日志里的Allocated host提示就知道是这问题ALLOWED_HOSTS [yourdomain.com, 你的服务器IP]Gunicorn的--workers数量我一般按“2 * CPU核心数 1”来设置并根据实际内存大小调整。家政系统早期用3到4个worker完全够。6.3 后续演进缓存、异步任务和接口拆分系统上线稳定后可以按需做这几件事Redis缓存。家政系统首页的服务项目列表、阿姨评分排名这类读多写少的数据用Redis缓存可以减少数据库压力。Django配置Redis缓存只需安装django-redisCACHES { default: { BACKEND: django_redis.cache.RedisCache, LOCATION: redis://127.0.0.1:6379/1, OPTIONS: { CLIENT_CLASS: django_redis.client.DefaultClient, } } }Celery异步任务。订单取消后要退款、服务完成后要自动生成结算单、每日要给管理员发送经营报表——这些任务都可以交给Celery去做。派单通知用Celery异步发送短信/微信避免接口等待外部服务响应。如果需要即时推送比如“后台有新订单前端马上弹出提醒”可以用WebSocket方案。Django支持channelsFlask可以用Flask-SocketIO。但家政系统的实际需求通常没那么即时站内信轮询足够应对90%的场景。不要一开始就上重技术方案先把业务跑起来才能知道哪里真正需要优化。7. 个人实操体会与建议最后一个章节说点做家政系统的心得也算是对整篇文章的收束。这个项目做完之后有几个判断越来越清晰。第一家政系统的核心永远是业务流程不是炫技。一个稳定的状态机、一趟顺畅的时间冲突检验、一张能对得上账的结算表比任何花哨的前端交互都更能留住客户。技术选型上Django很适合这种管理型业务而Flask则更适合需要高度定制、前后端分离的轻量场景。不必过度纠结框架之争把业务想清楚比什么都重要。第二数据模型设计一定要预留扩展余地。家政公司今天可能是“保洁家电清洗”下个月就可能是“保姆月嫂养老护理”。如果ServiceCategory表设计得足够灵活、订单表和用户表之间是通用外键而不是绑死单一角色后面加新服务就是插一条数据的事。反过来如果一开始把字段都写死在订单表里每加一个新服务就要改动表结构移动一次痛一次。第三开发过程中把Admin后台定制好能省掉大量重复劳动。我做家政系统时行政人员通过Admin就能处理订单状态、审核阿姨、查看客户投诉我几乎不用给这些功能单独写页面。这既是开发效率问题也是维护成本问题。最后分享一个小技巧所有订单时间相关字段前端表单提交时一定要规范成同一种格式。我建议前端统一用datetime-local输入组件后端用Django form的DateTimeField(parse_dateTrue)去解析。家政系统的预约时间一旦因为格式问题解析失败用户会直接流失这种细节一定要做产品级处理。做家政系统这类型项目最大的乐趣在于你可以看到一张表、一段代码如何真实改善一个小团队的日常协作。希望这篇文章能帮你少踩几个坑多省几天时间。有问题欢迎交流评论区见。