☰
Python+微信小程序构建房屋租赁报修与应收应付管理系统
2026/9/26 14:02:28 网站建设 项目流程

前两天终于把这套房屋租赁管理系统的后端和小程序端全部收尾,趁记忆还热乎,把完整思路和踩坑过程记录一下。这套系统用Python写了后端,微信小程序做了前端,业务上覆盖两大块:一块是房屋租赁里的故障报修,另一块是应收应付管理。后端框架用了Flask和Django,两个框架同时出现不是故意炫技,而是项目演进过程中自然形成的搭配,后面我会交代具体原因。如果你正在给公寓、二房东、物业公司做信息化系统,或者正在学Python后端的Web开发,这篇内容应该能给你不少可以照抄的模块和方案。

1. 项目背景:公寓运营为什么离不开数字化报修与对账

1.1 先从几个痛点说起

我之前帮一家小型租赁公司做过一套内部系统。他们的业务模式很简单:整租了几栋楼,再分成几十间房出租出去,租客多是刚毕业的上班族。以前租客要报修,只能在微信群里喊,或者打电话给管家,管家再用笔记本记下来,联系维修师傅上门。听起来没什么,真跑起来全是坑。

租客说“空调不制冷”,维修师傅到了说“得找厂家”,管家再转一道电话;修完多少钱、材料谁出、房东和租客各自承担多少,全凭群里聊天记录。月末一算账,管家拿来几张手写单据和微信转账截图,财务对着租金表一遍遍核,一天能核出三四个对不上的地方。房租催缴更是常规痛点,逾期一两周没人提醒,月底才突然想起来该收钱了。

这些看似不起眼的小事,放到几十上百间房里就变成每天都要处理的噪音。报修工单、应收账单、支付记录、维修费用如果没有一个统一的地方沉淀下来,规模越大管理成本越高。所以做这套系统的核心目的,不只是把流程搬到线上,而是让每一笔“事情”和每一笔“钱”都留下可追溯的数据。

1.2 这套系统到底做了什么

我要做的,是一套同时能跑在微信里和后台里的工具。租客端是一个微信小程序,可以提交报修、查工单进度、看账单、在线缴费;运营端是一个Python后端,维护房源、合同、账单和工单流转。我把项目分成两个模块:第一个是房屋租赁故障报修系统,第二个是应收应付管理系统。从代码层面看,它们共享同一套数据库,但在业务层面一个负责“事”,一个负责“钱”。

报修系统的核心是工单。租客提交报修单,管理员接单后指派维修师傅,师傅处理完填写费用和材料,租客确认验收,工单关闭。确认验收的时候,系统会根据费用类型自动生成一笔应收款或应付款。应收款是租客要承担的维修费,应付款是公司付给维修师傅的人工费或材料供应商的货款,它们都会进入应收应付管理模块。

应收应付系统的核心是账单和流水。应收侧管租金、押金、水电网费和租客承担的维修费,应付侧管维修人工、耗材采购、退款押金。每一笔收入或支出都对应一张可追溯的账单或凭证,这样到了月底不光能算出“这个月收了多少钱”,还能算出“哪些钱没收上来”、“修房子贴了多少钱”。

1.3 适合谁参考

如果你是Python开发者,正在找Web项目练手,这套系统的后端技术栈不算高,却把用户登录、权限、状态流转、账单对账、定时任务这些常见Web开发能力都覆盖了。如果你是物业系统外包项目的实施人员,这套业务模型可以直接复用到公寓、写字楼甚至园区场景里。我下面写的都是实际跑通过的做法,可以当成一份带注释的参考文档用。

2. 技术选型:为什么一套系统里同时出现了Flask和Django

2.1 一开始只用Flask可能更顺手

项目启动的时候,我只想赶紧把报修流程跑通,让租客不用再在群里喊话。Flask的好处是轻,一个文件就能把接口怼出来,路由、请求参数、返回JSON都很好理解。对于小程序后端来说,绝大多数接口就是接收POST、查数据库、返回状态,Flask完全够用。

我当时在虚拟环境里装好Flask、SQLAlchemy和PyMySQL,花了半天就写完了“创建报修单”和“查询列表”两个接口。开发阶段用Flask内置服务器跑,前端小程序填上内网IP,关掉域名校验,就能联调。效率很高,尤其适合一个人迅速验证业务想法。

但项目继续往后推,问题来了。报修单需要管理员后台,要区分角色权限,要维护楼栋、房间、合同,后来还要接账单和支付回调。如果这些都用Flask手写,工作量会指数增加。Django自带的Admin后台、ORM、迁移工具、认证体系能省掉很多基础工作。于是我在第一版跑通后,把后台管理和财务部分迁到了Django,报修API继续留在Flask侧。

2.2 Flask和Django分工协作的架构

最后形成的架构是:

  • Flask服务:专门提供小程序端调用的报修类API,包括创建工单、查询工单、上传图片、状态变更通知。
  • Django服务:负责房屋、租客、合同、账单、付款记录的管理,提供Django Admin给运营人员使用,同时暴露一部分统计和账单API给小程序的账单页。
  • 共用同一个MySQL数据库。Flask通过SQLAlchemy读取同一套表,Django通过自己的ORM管理同一套表,两边通过业务字段关联。
  • Redis用来缓存登录态和工单状态,避免频繁读写数据库。

严格来说,一个项目里同时维护两个Web框架会增加部署复杂度,但并没有想象中那么吓人,只要定义好边界,谁负责哪些表、哪些接口是稳定的,两个服务就能并行开发部署。如果你是一个人开发,我更推荐这种做法:把快速迭代的部分放在Flask里,把需要管理的部分放在Django里,风险会小很多。当然,如果一开始团队能力足够,直接全用Django也没有问题,完全取决于项目节奏和人员情况。

有人会觉得Django和Flask混用很别扭,但实际用下来,真正让你头疼的往往不是框架本身,而是跨服务的接口约定和数据库字段约定。把公共的表结构定义清楚,用一套命名规范管理,两个框架其实可以相安无事。

2.3 开发环境的细节

我用的Python 3.10,装依赖的时候建议用虚拟环境。无论你用Flask还是Django,先建venv,再装依赖,避免系统Python环境被弄乱。用VSCode开发时记得把解释器指到venv的Python,否则运行时会提示找不到flask模块。

数据库我选了MySQL 8.0,字符集utf8mb4,因为报修描述和账单备注会出现中文和emoji。驱动建议用PyMySQL,Django里配置好pymysql后要把install_as_MySQLdb()写进__init__.py,不然会报No module named MySQLdb。MySQL 5.7也能跑,但8.0对JSON字段和窗口函数的支持更好,统计报表写起来省心很多。

3. 业务设计与数据模型:让报修工单和账单挂上钩

3.1 从报修到对账的完整链路

在设计数据库之前,先把业务闭环画出来。租客登录小程序,选择所在房源和房间,填故障类型和描述,可拍照上传;提交后生成待接单工单。管理员在后台看到新工单,手动指派给维修师傅;师傅接单后状态变为维修中,完成后填写维修结果、人工费和材料费。租客确认后工单关闭,同时系统创建一笔费用账单。

费用账单这里有两种走向:如果维修责任在租客,比如人为损坏,账单记到租客名下,进入应收;如果责任在公司或房东,比如自然老化,这笔费用记到公司名下,进入应付,之后付给维修师傅或材料商。每个月末,系统按房源维度汇总应收、实收、欠收以及应付、已付、未付,就是最基础的对账报表。

这段链路看着简单,但每走一步都在产生业务数据。报修单关联房子、租客、维修师傅、金额;账单关联合同、报修单、收款记录。最后所有数据汇总到一张对账表,财务才敢对数字负责。

3.2 数据模型长什么样

我用SQLAlchemy风格把核心表写出来。字段没有刻意精简,都是实际用到的,这样理解起来更直接:

class Building(db.Model): __tablename__ = 'building' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) address = db.Column(db.String(255)) rooms = db.relationship('Room', backref='building') class Room(db.Model): __tablename__ = 'room' id = db.Column(db.Integer, primary_key=True) building_id = db.Column(db.Integer, db.ForeignKey('building.id')) room_no = db.Column(db.String(20), unique=True) rent_amount = db.Column(db.Numeric(10, 2), default=0) status = db.Column(db.String(20), default='empty') # empty / rented / repair class Tenant(db.Model): __tablename__ = 'tenant' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) phone = db.Column(db.String(20)) id_card = db.Column(db.String(30)) class Lease(db.Model): __tablename__ = 'lease' id = db.Column(db.Integer, primary_key=True) tenant_id = db.Column(db.Integer, db.ForeignKey('tenant.id')) room_id = db.Column(db.Integer, db.ForeignKey('room.id')) start_date = db.Column(db.Date) end_date = db.Column(db.Date) monthly_rent = db.Column(db.Numeric(10, 2)) deposit = db.Column(db.Numeric(10, 2)) class RepairTicket(db.Model): __tablename__ = 'repair_ticket' id = db.Column(db.Integer, primary_key=True) lease_id = db.Column(db.Integer, db.ForeignKey('lease.id')) category = db.Column(db.String(50)) # 如空调、水电、门窗 description = db.Column(db.Text) images = db.Column(db.JSON) # 图片URL列表 status = db.Column(db.String(20), default='pending') assignee_name = db.Column(db.String(50)) applied_at = db.Column(db.DateTime, default=datetime.now) completed_at = db.Column(db.DateTime) labor_fee = db.Column(db.Numeric(10, 2), default=0) material_fee = db.Column(db.Numeric(10, 2), default=0) responsibility = db.Column(db.String(10)) # tenant / company

账单部分单独拆了一张表,用bill_type区分钱的名目:

class Bill(db.Model): __tablename__ = 'bill' id = db.Column(db.Integer, primary_key=True) lease_id = db.Column(db.Integer, db.ForeignKey('lease.id')) ticket_id = db.Column(db.Integer, nullable=True) # 如果是从报修生成的费用,记录工单ID bill_type = db.Column(db.String(20)) # rent / deposit / utility / repair / refund direction = db.Column(db.String(10)) # receivable / payable title = db.Column(db.String(100)) amount = db.Column(db.Numeric(10, 2)) due_date = db.Column(db.Date) status = db.Column(db.String(20), default='unpaid') # unpaid / paid / canceled paid_at = db.Column(db.DateTime)

这张Bill表是整个应收应付系统的主心骨。所有应收款和应付款都落到这一张表里,只是用direction区分方向,再配合bill_type知道钱的名目。这样统计报表只需要对Bill做GROUP BY,不用在多张表之间做UNION。

3.3 为什么要反复强调关联关系

我在第一版里把维修费用直接写进RepairTicket,没有单独生成Bill,当时觉得省事。后来发现月底对账时非常痛苦:工单里有一个费用,账单里没有,财务只能人工再去翻。后来改成在工单关闭时自动创建Bill,并且把ticket_id存进Bill表,问题才彻底解决。

这就是业务上最重要的“闭环”:报修工单和费用账单必须互相可查。从工单能查到生成的账单,从账单能倒查到关联工单。如果开发时没把这条链路建起来,后面每一张报表都要拼数据,越做越难维护。后来我还加了一个约束:同一张工单最多只能生成一笔待支付的维修费用账单,避免重复计费。

4. 核心代码实现:Flask、Django和小程序端的对接细节

4.1 报修工单状态机

工单状态不能散落在各个接口的判断里,我封装成一个常量类,然后在状态变更前统一校验:

class TicketStatus: PENDING = 'pending' # 待接单 ASSIGNED = 'assigned' # 已指派 IN_PROGRESS = 'progress' # 维修中 COMPLETED = 'completed' # 待验收 CLOSED = 'closed' # 已关闭 CANCELED = 'canceled' # 已取消

每次状态变更用一个装饰器或者中间层检查:

ALLOWED_TRANSITIONS = { TicketStatus.PENDING: [TicketStatus.ASSIGNED, TicketStatus.CANCELED], TicketStatus.ASSIGNED: [TicketStatus.IN_PROGRESS, TicketStatus.PENDING], TicketStatus.IN_PROGRESS: [TicketStatus.COMPLETED], TicketStatus.COMPLETED: [TicketStatus.CLOSED], }

只有在这里登记过的状态跳转才允许执行,否则直接返回错误。这个小设计帮我避开了很多“工单突然从维修中变成已取消”的乌龙。状态机会让代码更清晰,后期加“重新打开工单”这类功能时也只要在字典里加一条映射。

4.2 Flask侧报修接口

Flask侧主要给小程序提供JSON API,下面是一个创建报修单的简洁版本:

@app.post('/api/repair/tickets') def create_ticket(): data = request.get_json() token = request.headers.get('X-Token') tenant = auth_service.verify_token(token) if not tenant: return jsonify(code=401, msg='登录已过期'), 401 ticket = RepairTicket( lease_id=tenant.current_lease_id, category=data.get('category'), description=data.get('description'), images=data.get('images', []), status=TicketStatus.PENDING ) db.session.add(ticket) db.session.commit() return jsonify(code=0, data={'ticket_id': ticket.id})

这里有几个容易踩坑的地方。一是不要直接使用request.form,小程序端如果设置header['content-type'] = 'application/json',后端拿到的就是JSON体,必须用request.get_json()。二是token校验必须在进入业务逻辑前完成,不能等建完单再校验,否则会写入脏数据。三是图片不要和表单一起提交,而是先调上传接口拿到URL,再提交表单,速度更快,也方便失败重试。

查询工单时按租客维度查,只返回自己名下的记录:

@app.get('/api/repair/tickets') def list_tickets(): tenant = auth_service.verify_token(request.headers.get('X-Token')) tickets = RepairTicket.query.filter_by(lease_id=tenant.current_lease_id) \ .order_by(RepairTicket.applied_at.desc()).all() return jsonify(code=0, data=[ticket.to_dict() for ticket in tickets])

4.3 Django侧账单和统计接口

Django这边我用的是Django REST Framework。账单列表接口很简单:

class BillViewSet(viewsets.ModelViewSet): queryset = Bill.objects.select_related('lease__room').all() serializer_class = BillSerializer filterset_fields = ['lease_id', 'direction', 'bill_type', 'status']

需要注意Django默认权限比较严格,小程序端调用这些接口时,不要用Session认证,换成TokenAuthentication更合适。在settings.py里设置:

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], }

Django的QuerySet有个容易被新手忽略的点:删除对象时Bill.objects.get(id=1).delete()会直接删掉整行。如果账单已经支付过,就不该删除,而应该改状态为canceled。业务上“作废”和“删除”是两个动作,数据库里尽量不要物理删除有业务含义的数据。这一点在开发里非常容易忽略。

再看一个对账统计的写法。要统计某个月所有应收和应付的汇总,可以用Django的聚合函数:

from django.db.models import Sum def monthly_report(year, month): bills = Bill.objects.filter(due_date__year=year, due_date__month=month) receivable = bills.filter(direction='receivable').aggregate( total=Sum('amount'), paid=Sum('amount', filter=Q(status='paid')) ) payable = bills.filter(direction='payable').aggregate( total=Sum('amount'), paid=Sum('amount', filter=Q(status='paid')) ) return { 'receivable_total': receivable['total'] or 0, 'receivable_paid': receivable['paid'] or 0, 'payable_total': payable['total'] or 0, 'payable_paid': payable['paid'] or 0, }

线上跑的时候,我发现一个坑:Sum('amount', filter=Q(status='paid'))里的filter只支持Django 2.0以上,且聚合字段如果所有记录都被过滤掉,返回的是None,不是0。所以后面加or 0很有必要。

4.4 微信小程序端对接与常见适配

小程序端用原生写法,不依赖uni-app。在utils/request.js里统一封装请求:

const BASE_URL = 'https://api.example.com'; function request(path, method = 'GET', data = {}) { const token = wx.getStorageSync('token'); return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + path, method, data, header: { 'Content-Type': 'application/json', 'X-Token': token }, success: res => { if (res.data.code === 0) resolve(res.data.data); else if (res.data.code === 401) { wx.removeStorageSync('token'); wx.navigateTo({ url: '/pages/login/login' }); } else reject(res.data.msg); }, fail: reject }); }); }

登录时用wx.login()拿code,再传给后端换token。后端拿到code后调用微信接口换取openid,再在本地签发自己的token。微信的code本来就是一次性凭证,有效期只有五分钟,所以不要再缓存code。

页面适配上的经验也值得记录。微信小程序的wx.request只认https和小程序后台配置的合法域名,开发阶段可以在开发者工具里勾选“不校验合法域名”,但真机预览必须填真实域名。顶部导航栏的高度不用写死,用wx.getMenuButtonBoundingClientRect()获取胶囊位置,再估算导航栏高度,不同机型都能适配。图片上传用wx.chooseMedia拿到临时文件路径后,再用wx.uploadFile传给后端,不能直接拿临时路径当永久地址。

账单页和工单列表页的缓存,我建议不要简单用wx.setStorageSync存原始数据,应该带上自定义过期时间戳。比如缓存5分钟,启动时先比较时间,过期了再重新拉取,否则会出现用户已付款但页面还显示未付款的情况。

5. 部署与联调:从本地跑通到上线踩过的坑

5.1 本地开发调试的真实环境

联调阶段很多人会卡在小程序访问本地Flask服务这一步。最直接的办法是让手机和电脑在同一个局域网内,小程序请求地址用电脑的局域网IP,比如192.168.x.x:5000,同时开发工具勾选不校验合法域名。如果手机扫码预览,也需要打开调试模式,否则安卓真机仍然会因为域名没校验而拒连。

更省心的方式是买一个带HTTPS的内网映射工具,把本地服务的公网地址配到小程序后台开发域名里,这样每台电脑都能马上用真机调试。我在项目里用过这种方式,省了很多配路由的麻烦。如果你的团队不方便用这类工具,至少也要保证测试环境有固定的公网地址,不要每天改来改去。

后端两个服务同时开发时,端口别冲突。Flask我用了5000,Django开发服务器用了8000,前端小程序根据场景分别请求不同端口。上线后通过nginx统一入口,分别代理到两个服务,比如/api/repair/*到Flask,/api/bills/*到Django。小程序端只保留一个API地址,对后续迁移友好。

5.2 用gunicorn和nginx上线跑

生产环境我建议用gunicorn跑Flask和Django的WSGI应用。Flask侧:

gunicorn -w 4 -b 127.0.0.1:5000 app:app

Django侧:

gunicorn -w 4 -b 127.0.0.1:8000 config.wsgi:application

两者都监听本机端口,nginx在外面做HTTPS和反向代理。不要把gunicorn直接绑到0.0.0.0上,让nginx管理对外流量,后面加SSL证书、加限流都方便。

nginx配置里最重要的一段是转发请求头。小程序端带过来的X-Token必须原样向后传到Django或Flask,否则Django的TokenAuthentication会直接401。我吃过这个亏,排查了两小时才发现是nginx配置把自定义头给吞了。在location里加一行proxy_set_header X-Token $http_x_token;就解决了。

5.3 微信生态里的配置清单

上线前微信小程序后台有几项必填:request合法域名必须是https,uploadFile合法域名也要填。如果用了微信支付,要开通商户号并把支付回调地址配到服务器上,回调地址必须是公网可访问的HTTPS。订阅消息要提前申请模板,比如“报修进度通知”“账单缴费提醒”,每个模板ID都要在代码里配置好。

订阅消息不是用一次就永久有效,用户点同意后只能发送一次模板消息。如果报修工单要多次提醒,最好在用户每次查看工单时重新发起订阅,否则第二次发送会提示“用户未授权”。这个问题很容易被忽略,上线后提醒消息会莫名消失。我的解决办法是在工单详情页的onLoad里主动调用wx.requestSubscribeMessage,提前拿下一次授权。

6. 常见问题与排查实录

6.1 小程序连不上后端

现象原因排查方法
请求直接fail域名没配或未勾选“不校验合法域名”开发者工具打开不校验,真机预览配好https域名
connect ECONNREFUSED后端服务没启动,或者监听端口不对检查本地进程和端口,确认防火墙放行
请求返回200但code是401token没取到或过期打印请求头里的X-Token,确认登录后再请求
安卓真机请求失败,iOS正常小程序后台域名配置只填了https,未填uploadFile域名在平台里把所有域名类型都补全

排这种问题时,我的习惯是先看小程序的Network面板,再去看后端日志。小程序面板里能明确看到请求URL、状态码和返回内容,比一点一点猜快很多。

6.2 报修工单状态错乱和数据不一致

多端同时操作时报修单状态容易错。比如管理员在电脑上把工单指派给师傅,师傅在小程序上接单时,可能读到的是旧状态。解决办法是在修改状态时带上当前状态条件,更新语句写成:

RepairTicket.query.filter_by(id=ticket_id, status=old_status).update( {'status': new_status} )

如果没有匹配行,说明状态已经被别人改过,返回冲突错误让前端刷新重试。这种乐观锁的做法比单纯加锁要好,不会长时间锁表,并且很符合工单这种低频更新场景。

另一个容易踩的是维修费用生成账单时的一致性。我在Flask里更新工单完成后,又去Django那边生成账单,早期因为两个服务独立提交,出现过工单已完成但账单没生成的情况。后来我把“完成工单”和“生成账单”放到同一个数据库事务里,同时更新RepairTicket和Bill,如果bill创建失败,工单状态也回滚。Flask里用SQLAlchemy的db.session.begin_nested()处理,Django那边用transaction.atomic()。

6.3 前后端页面显示和缓存问题

有段时间租客反馈账单页显示金额不对,我把问题缩小到缓存上。小程序从Bill接口拿数据存进wx.setStorageSync,但页面打开时没有先清理旧缓存,用户付完款后账单状态还是旧的。解决办法是给缓存加版本号和时间戳,读取缓存时判断是否过期,7天内不过期,过期就重新请求。这个设计很简单,但很实用。

顶部导航栏高度适配是另一个高频问题。小程序iPhone和安卓机的状态栏高度不一样,直接用固定的navigationBarHeight会出现标题偏上或偏下。我写了一个工具函数,在onLoad里调用:

const { statusBarHeight } = wx.getSystemInfoSync(); const menu = wx.getMenuButtonBoundingClientRect(); const navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height;

用动态计算出的高度去布局,基本不会被机型问题烦到。如果你的页面有吸底按钮或者自定义导航栏,这套动态高度方案能直接复用。

6.4 Django删除对象和静态文件注意事项

如果你用Django Admin管理后台,很容易遇到“删除对象”的问题。我在运营后台给管理员提供了作废账单按钮,但一开始是调用delete()物理删除。后来财务审核时发现,一张已经被扫码支付的账单被删掉后,支付记录在微信商户端还躺着,到了月底怎么都对不上。改成状态canceled之后,保留账单和支付流水,报表里过滤掉已取消的账单,账才平下来。

Django的静态文件在开发环境没问题,上线后常常出现admin样式丢失的情况。原因是DEBUG = False后,Django不会自动提供静态文件服务,需要执行python manage.py collectstatic,再在nginx里加静态文件alias。如果你用VSCode写Django模板,发现{% static %}标签引用的图片显示不了,十有八九是STATICFILES_DIRS没配好或者目录不对。

6.5 定时任务和消息推送经验

应收应付里最有用的一个功能是逾期提醒。我是用Django的manage.py自定义命令,配合crontab每天上午9点执行:

0 9 * * * cd /opt/lease_project && venv/bin/python manage.py send_overdue_reminders

命令里查询离到期日3天和已逾期的应收账单,再调用微信订阅消息接口给租客推送提醒。这里要注意,推送服务如果部署在Flask侧,也可以通过HTTP调用,但必须处理好重试和日志。微信接口返回失败时不能只print,要落到一张message_log表里,否则消息丢了完全不知道。

7. 项目管理层面的复盘与建议

7.1 人和流程的边界从一开始就要定清

这套系统最有价值的经验不是代码,而是角色边界。租客只在微信小程序里操作,运营人员只在Django Admin里操作,维修师傅只用一个简化版的小程序页面。每个人看到的界面完全不同,数据权限不能混。小程序端的用户是租客,天然只能看到自己合同下的数据,后台管理员则可以跨房源查看。这些权限规则我一开始没定细,结果出现了租客能看到其他房间工单的情况,改权限花了半天时间。

功能边界也要在开发前划清楚。Flask负责什么、Django负责什么、哪些表只有谁写,如果我一开始就定义清楚,后面不会出现两边各写一遍导致字段冲突。个人开发者很容易犯这个毛病,今天想用Flask实现一切,明天觉得Django更全,结果代码越来越乱。

7.2 小步快跑比一步到位更重要

如果你是自己练手,可以从“一个Flask项目跑通报修API”开始,跑顺了再往里加Django后台和账单模块。不要上来就同时整两个框架,我也不是一开始就计划混用的,而是在业务自然推进中演变成现在的分工。先让一条业务线闭环,再扩展下一条,是这类项目最稳的做法。

最后再分享一个开发效率技巧:小程序端统一封装请求、统一处理401跳转,后端每个接口返回{code, msg, data}结构,能省掉大量联调扯皮。这个结构看着老土,但最好用,不管是一个人还是几个人协作,接口约定一致比什么都重要。这套系统跑起来之后,那家公司的管家再也不用晚上十点对着微信群抄报修记录了。你如果也在做类似的系统,照着这套思路把报修和账单串起来,基本上一周就能跑通第一版。

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

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

立即咨询