ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Python Flask快递驿站取件管理系统开发全流程解析

Python Flask快递驿站取件管理系统开发全流程解析 我们平时去小区快递代收点取件最烦的就是满货架翻找和人工核对身份。去年我给本地一家快递驿站做了一套取件管理系统用它把入库、短信通知、取件验证、异常件处理整个链路串了起来今天把整个项目从设计到落地的经验做一个完整复盘。项目本身基于Python语言Web框架用的是Flask配套PyCharm开发环境核心功能包括快递入库、取件码自动发送、身份校验和后台统计。如果你正打算用Python做类似的管理系统或者正在选型Flask和Django之间纠结这篇内容可以帮你节省不少弯路。1. 项目整体设计与技术选型思路1.1 物流取件系统的核心需求拆解做这套系统之前我专门去驿站蹲了几天观察日常取件流程。表面看就三件事快递到了入库、通知用户来取、用户报码取件。但实际操作中有很多细节入库的快递要记录单号和货架位置用户取件时需要验证身份防止冒领异常件需要单独处理还有每天的取件量统计和滞留件提醒。拆解下来核心功能模块应该是这五个用户管理模块负责注册、登录和个人信息维护手机号既是登录凭证也是接收通知的通道快递管理模块覆盖快递的入库、上架、出库和状态跟踪每一条快递记录都要关联到具体的货架位置取件验证模块这是整个系统的安全核心需要生成一次性取件码取件时通过取件码加手机尾号双重验证通知模块快递到达后自动给用户发送短信通知统计报表模块给驿站经营者提供每日入库量、取件量、滞留情况的汇总数据。看清这个业务模型之后技术选型就有了明确目标。系统不需要特别复杂的高并发架构核心是业务逻辑清晰、开发效率高、后续好维护。对于一个日处理几百件快递的小型驿站单机部署、SQLite或MySQL存数据就足够了。我选择Flask作为主框架一方面是这套系统规模不需要Django那么重的全家桶另一方面是Flask的灵活度更高快递管理的业务逻辑本身就是定制化的轻框架更容易把每个环节控制在自己手里。1.2 为什么用Flask而不是Django很多朋友会在这两个框架之间纠结网上的比较文章也特别多。我基于这个实际项目说说自己的判断。如果项目核心是一个数据模型比较复杂、需要大量标准后台管理的应用Django自带Admin后台和ORM确实能省大量重复劳动。但如果业务逻辑是高度定制化的比如快递的状态流转、取件码这种临时凭证的生成和校验Flask用装饰器自己控制路由和中间件反而更顺手。取件管理系统正好落在两种情况的中间地带。它确实需要后台管理快递数据但后台的形式比较固定用Flask配一个简单的后台模板或引入现成插件都能解决。而快递状态流转这种动态逻辑才是系统的核心这部分用Flask的蓝图和视图函数拆分得一清二楚写出代码来和中文业务描述几乎一一对应后期接需求也好沟通。另外这个项目还有一个关键因素就是开发效率。Flask本地调试的时候debug模式特别方便代码改了自动重载配合PyCharm的调试器基本可以做到断点跟到下一条业务线。如果你坚持要用Django这个项目也不是不能做Django的ORM在快递单号、货架位置、取件记录这种关联查询上确实更强。只是对于单机小规模项目来说两个框架都能完成任务Flask可以把代码结构做得更直观尤其是给新手演示整个请求到响应的流程时Flask的显式路由比Django的URLconf更能让人一眼看明白。1.3 开发环境和工具链的配置开发工具我选择的是PyCharm专业版这个选择主要是基于远程部署和数据库工具的考虑。高手用VSCode也能写但PyCharm在虚拟环境管理、Flask模板调试、数据库插件集成这几块做得比较省心。项目新建时直接选择Flask项目模板PyCharm会自动帮我们建好虚拟环境和项目结构省去了手动配置一堆依赖的时间。直接说这套环境怎么搭。本地需要有一个Python 3.8以上的解释器建议直接到Python官网下载安装包。Mac用户直接用Homebrewbrew install python3一行搞定。然后是PyCharm社区版做Flask开发也够用但专业版支持数据库工具、Django支持和远程解释器如果你电脑配置允许又有长期做Web开发的计划专业版确实更顺手。装好PyCharm后新建项目时选择Flask模板它会在项目目录下自动生成app.py和static、templates文件夹这两个目录分别存放静态资源和HTML模板。依赖管理我用的是requirements.txt加虚拟环境的组合。虚拟环境是Python项目必须做的隔离措施防止不同项目之间的包版本互相冲突。PyCharm新建项目默认就会创建venv目录每次从终端运行项目之前要先激活虚拟环境。Windows下是venv\Scripts\activateMac和Linux是source venv/bin/activate。在这个环境里需要安装的核心依赖包括Flask、Flask-SQLAlchemy、Flask-Login、Flask-WTF、requests这些分别对应Web框架、ORM数据库操作、登录会话管理、表单处理和短信接口调用。2. 数据库建模与核心表结构设计2.1 用户表、快递单表和取件记录表数据库设计是整个项目的地基表结构没想清楚后面改起来特别痛苦。这套系统我最终规划了四张核心表分布在用户端和管理端。第一张是user表存储用户基本信息。字段包括自增主键id、唯一索引的手机号phone、加密后的密码password_hash、用户的真实姓名real_name、房间号或门牌号address以及注册时间created_at。手机号加唯一索引是为了防止一个号码重复注册同时也作为取件验证的关联字段。第二张是package表也就是快递单表。字段包括主键id、快递单号tracking_number、快递公司company、收件人手机号recipient_phone、货架号shelf_code、入库时间created_at、状态status可选值有已入库、已通知、已取件、已退回、取件码pickup_code、取件时间picked_up_at。其中tracking_number建议加索引因为快递入库和查询时最频繁的检索条件就是单号。第三张是pickup_record表记录每一次取件操作的痕迹。字段包括id、关联快递单号package_id、取件人手机号pickup_phone、验证码code_used、取件时间created_at、操作员operator_id。这张表是审计用的一旦出现冒领、错领纠纷可以通过这张表回溯到底是谁、什么时候、凭哪个码取走了快递。用户端查自己取了哪些件也靠这张表关联查询。第四张是admin表对应管理端账户。字段相对简单id、username、password_hash、created_at。快递驿站一般是老板或店员操作后台账户数量极少不需要复杂的角色权限设计两个角色足够了。系统里还有一个全局参数表的设计用来存短信API的key、每日取件提醒时间、滞留判定天数这些业务参数这样调整业务规则时不用改代码重新部署。2.2 状态机设计快递在系统中的生命周期快递从到达驿站到被取走或退回整个生命周期应该是一个清晰的状态流转过程这也是系统里最容易写乱的地方。最初版我随手用字符串直接更新状态后来发现一旦状态分支多了代码里到处都是判断改一个逻辑要翻好几个文件。后来老老实实做了状态机。快递初始状态是ARRIVED此时快递刚到达驿站只有管理员能看到这条记录。管理员执行入库操作后状态变为STORED这是快递正式上架的状态。如果启用了短信通知功能系统会在入库后自动发送取件通知状态更新为NOTIFIED。用户到店报出取件码管理员验证通过快递出库状态变为PICKED_UP同时记录取件时间。如果快递入库超过设定天数比如7天仍未取系统将状态标为OVERDUE管理员可以选择联系用户或做退回处理退回后状态为RETURNED。状态流转的代码我用一个专门的服务模块来管理每个状态的变化都走同一个入口函数入口函数里先校验当前状态是否可以跳到目标状态。比如一个PICKED_UP的快递肯定不能又变回STORED一个已经RETURNED的快递也不能再被取件码验证通过。这种集中管理的方式加上完整的日志记录排错的时候效率会高很多。2.3 用SQLAlchemy定义模型和关系ORM我用的是Flask-SQLAlchemy这是Flask社区最主流的ORM方案。定义模型时需要注意关联关系的设计package表和pickup_record表之间是典型的一对多关系一个快递可以有多条取件记录理论上一条就够但设计上一对多是防止意外情况发生。admin表和pickup_record表之间也有操作员关联方便按操作员统计工作量。直接上实际代码。模型定义这部分db.Model是SQLAlchemy的模型基类db.Column定义字段类型和约束relationship定义模型间的关系backref让反向查询更方便。from flask_sqlalchemy import SQLAlchemy from datetime import datetime db SQLAlchemy() class Package(db.Model): __tablename__ package id db.Column(db.Integer, primary_keyTrue) tracking_number db.Column(db.String(64), uniqueTrue, indexTrue) company db.Column(db.String(32)) recipient_phone db.Column(db.String(20), indexTrue) shelf_code db.Column(db.String(16)) status db.Column(db.String(16), defaultARRIVED) pickup_code db.Column(db.String(8)) created_at db.Column(db.DateTime, defaultdatetime.now) picked_up_at db.Column(db.DateTime, nullableTrue) pickup_records db.relationship(PickupRecord, backrefpackage, lazydynamic) class PickupRecord(db.Model): __tablename__ pickup_record id db.Column(db.Integer, primary_keyTrue) package_id db.Column(db.Integer, db.ForeignKey(package.id)) pickup_phone db.Column(db.String(20)) code_used db.Column(db.String(8)) operator_id db.Column(db.Integer, db.ForeignKey(admin.id)) created_at db.Column(db.DateTime, defaultdatetime.now)这里有一个细节值得提起。用户查询“我有哪些快递待取”时常规思路是直接扫package表里的收件人手机号但这样如果同一个手机号在不同快递单号下存在多条记录查询结果会有重复。加上PickupRecord这张关联表后同一个快递被取走时有明确的动作记录查询已取和历史记录都非常清晰。从实体关系上可以理解成每取走一个包裹系统自动生成一条审计操作这和现实中扫码出库的动作是对应的。3. 核心功能模块的实现与踩坑记录3.1 用户端注册、登录与我的快递用户端页面我控制在三个主要界面注册登录页、首页列表页、取件详情页。注册时手机号和密码是必填项密码不能明文存储要用werkzeug.security的generate_password_hash做哈希处理。登录成功后用Flask-Login管理会话用户id写进session后续请求通过装饰器login_required判断登录状态。涉及数据库密码存储的还有一个细节哈希一定不要用MD5或SHA1这种弱算法要用带盐的哈希方案werkzeug默认的pbkdf2:sha256就是一个可靠选择。“我的快递”列表是这个模块的核心列表显示当前手机号关联的所有未取件包裹包括快递公司、货架位置、取件码和距离取件还剩多少天。查询逻辑用SQLAlchemy的三行代码就能搞定pending_packages Package.query.filter( Package.recipient_phone current_user.phone, Package.status.in_([STORED, NOTIFIED, OVERDUE]) ).order_by(Package.created_at.desc()).all()这里需要注意filter后面是多个条件的组合如果传了不存在的状态值查询不会报错但会返回空列表所以状态值的管理最好做一层枚举校验避免手滑拼错字符串。首页列表还有一个滞留提醒显示系统会自动对比当前时间和入库时间超过设定天数的包裹在页面上用红色标签标出“已滞留”。实现方式是在后端查询时算出每个包裹的入库天数传给模板做条件判断。这个功能虽然简单但在实际使用中特别受驿站欢迎因为滞留件占用货架资源是驿站最头疼的问题之一。3.2 快递入库与货架管理入库是整个流程的起点。管理端的入库页面支持两种方式逐件手动录入和批量导入。手动录入的字段包括快递单号、快递公司、收件人手机号、货架号录入后系统自动生成取件码。批量导入的场景通常发生在快递车一次送来几十上百件时我做了CSV模板下载功能管理员按模板填好一次性导入入库效率能提升一个量级。货架号的管理也做了规范化处理。实际驿站的货架一般是字母加数字的组合比如A区第3层就是A-3。我建议入库时货架号做成下拉选择数据源来自后台维护的货架配置表而不是让管理员自由输入。原因是自由输入的污染非常严重同一个货架“A-3”“A3”“A 03”可能存在多条数据取件时用户报一个架号管理员找到正确位置的时间反而增加了。这个数据规范化的思路同样适用于快递公司的名称下拉选择比手输靠谱得多。取件码的生成是入库模块的关键细节。取件码设计为4位数字范围从0000到9999入库时随机生成。生成时要检查是否和当天其他待取快递的取件码重复重复就重新生成。为什么不直接用6位数字因为取件人在驿站报码时4位数字的记忆负担和输入成本都更小。至于安全性取件码只是第一道验证取件时还会要求核对手机尾号双层验证基本可以覆盖绝大多数小站的安全诉求。import random def generate_pickup_code(): while True: code f{random.randint(0, 9999):04d} exists Package.query.filter( Package.pickup_code code, Package.status.in_([STORED, NOTIFIED, OVERDUE]) ).first() if not exists: return code这个随机码的循环生成逻辑最坏情况是当天待取快递接近一万件时可能出现多次碰撞重试。实际场景中一个小城的驿站一天能有几百件就已经很夸张了所以这个方案完全够用不必引入复杂的编号算法。3.3 取件验证流程双重校验怎么实现取件验证是整个系统安全性的核心。用户到驿站后报出取件码管理员在取件页面输入取件码系统查询对应的未取件快递记录。此时先校验取件码是否存在如果不存在页面直接提示“取件码无效”。然后进入第二步校验管理员需要向用户确认手机尾号输入后和快递记录的收件人手机尾号比对一致则验证通过不一致就提醒重新核对。这套逻辑在首页做了一个简洁的对取件码的快速查询入口应该说是整个项目里使用最频繁的功能。为提高效率我将取件验证做成了单独的页面支持连续取件。一个用户取多个包裹时不用反复输入手机尾号页面会自动记住最近验证过的手机号。实现时就是在session中临时存一个last_verified_phone的键校验一个新的取件码时先检查手机号是否一致一致则直接通过。def verify_pickup(code, phone_tail): package Package.query.filter_by( pickup_codecode, status.in_([STORED, NOTIFIED, OVERDUE]) ).first() if not package: return False, 取件码不存在或已被使用 if not package.recipient_phone.endswith(phone_tail): return False, 手机尾号不匹配请重新核对 package.status PICKED_UP package.picked_up_at datetime.now() record PickupRecord( packagepackage, pickup_phonepackage.recipient_phone, code_usedcode, operator_idcurrent_admin.id ) db.session.add(record) db.session.commit() return True, 取件成功有一个需要注意的地方取件成功后快递状态变化是敏感操作一定要在同一个事务里完成状态更新和取件记录插入两者要么同时成功要么同时失败。我在最初版的时候懒得写事务出现过快递状态已经变成已取件但取件记录没插入成功的情况后面排查数据对不上花了不少时间。自那以后涉及多个表写入的操作我统一封装成事务操作并且加了db.session.rollback()的异常处理。3.4 短信通知从0到1对接一条验证码短信熬夜做完了入库和取件短信通知可以说是这个项目里最折腾的模块。第一次对接短信API的时候没有经验以为拿到签名和模板就完事了实际跑的时候各种问题接踵而来。最常见的坑模板内容必须和申请的模板完全一致连空格和标点都不能改签名需要提前审核个人开发者压根没有签名申请权限必须用企业资质短信平台的accessKey和secretKey这些密钥绝对不要写在前端代码里也不建议硬编码在后端代码里应该放到环境变量或配置文件里。我这里用的是阿里云短信服务新用户会有一定免费额度个人测试够用了。整个对接流程可以拆成四步。第一步是在阿里云控制台申请签名签名必须是企业或品牌的名称个人测试建议用一个和项目相关的名字。第二步申请短信模板内容类似于“您的快递已到达XXX驿站取件码为${code}请及时领取”。第三步在阿里云RAM访问控制里创建AccessKey权限只授予短信发送的API接口。第四步写发送逻辑加一个独立的send_sms.py模块封装发送函数调用的是阿里云官方SDK。from aliyunsdkcore.client import AcsClient from aliyunsdkdysmsapi.request.v20170525.SendSmsRequest import SendSmsRequest def send_pickup_sms(phone, code, company_name): client AcsClient(your_access_key, your_access_secret, cn-hangzhou) request SendSmsRequest() request.set_PhoneNumbers(phone) request.set_SignName(你的签名) request.set_TemplateCode(SMS_xxxxxxx) request.set_TemplateParam(f{{code:{code}}}) response client.do_action_with_exception(request) return response短信模块上线后一定要验证一件事就是套餐包的余额。有些平台默认余额不足也不会报错响应里返回一个特定的错误码代码里如果没做异常捕获用户收不到短信但系统还显示发送成功这个体验就太差了。我在发送逻辑里加了返回码判断非成功状态写日志并给出提示。另一个需要在配置里设置的是发送频率限制同一手机号60秒内不能重复发送防止管理员手滑多次点击导致用户收到一堆相同短信。4. 项目运行与部署的实操经验4.1 PyCharm中运行和调试Flask应用在PyCharm里运行Flask项目非常省心。项目结构建好后直接配置一个Flask Server运行配置Python解释器选虚拟环境里的那个target选app.py勾选FLASK_DEBUG模式。这样启动后代码修改会自动重载配合PyCharm的断点调试可以在视图函数里一行行跟踪请求流程排查问题比打print快得多。有一个小坑需要提醒。Flask默认端口是5000某些系统或容器环境可能会占用这个端口。启动时如果看到Address already in use的报错不是代码问题是端口冲突改一下端口就行。在app.run()里指定端口if __name__ __main__: app.run(host0.0.0.0, port8000, debugTrue)host0.0.0.0的意思是监听所有网卡地址这样同一局域网内的手机或其他电脑也可以访问到这个服务特别适合驿站里用电脑当管理端、用户用手机访问查询页面的场景。需要特别注意debugTrue绝对不要在生产环境开启调试模式会暴露详细的报错信息和代码片段有严重的安全隐患。生产环境要用独立的WSGI服务器如Gunicorn来跑Flask应用。4.2 初始化数据创建一个管理员账号和一个演示用户项目跑通后第一件事就是初始化管理员账号。我习惯直接用一个独立的Python脚本来操作而不是通过网页或命令行手工录入。在项目根目录下创建一个init_db.py脚本里做三件事建库建表、创建管理员、创建一个演示用户并打几条示例快递数据。from app import app, db from models import Admin, User, Package from werkzeug.security import generate_password_hash with app.app_context(): db.create_all() admin Admin(usernameadmin, password_hashgenerate_password_hash(admin123)) user User(phone13800138000, password_hashgenerate_password_hash(123456), real_name张三, addressA栋302) db.session.add(admin) db.session.add(user) db.session.commit() print(初始化完成)这份脚本背后的逻辑是管理端的账号不应该和用户端注册流程混在一起实际驿站里管理员账号通常由系统部署者创建并告知老板而不是通过页面注册。db.create_all()只在第一次建表时有用后面模型改了要通过迁移工具或重建表来处理千万不要在生产环境直接执行删表重建。我这里补充一下SQLite数据库文件会被PyCharm识别并显示在侧边栏可以直接看表数据方便调试非常顺手。4.3 Flask项目结构的组织方式项目写多了之后会发现Flask项目的坑不在于框架本身而在于项目结构写乱了后面根本不想维护。建议从一开始就按照功能模块划分目录而不是把所有路由写在一个app.py里。我最终采用的结构是express_management/ ├── app.py # 应用入口创建app和db实例 ├── config.py # 配置文件存放数据库地址、密钥、短信API参数 ├── models/ │ ├── __init__.py │ ├── user.py # 用户模型 │ ├── package.py # 快递单模型 │ ├── pickup_record.py # 取件记录模型 │ └── admin.py # 管理员模型 ├── views/ │ ├── __init__.py │ ├── user_views.py # 用户端路由 │ ├── admin_views.py # 管理端路由 │ └── api_views.py # 供小程序或前端调用的API ├── services/ │ ├── __init__.py │ ├── sms_service.py # 短信发送服务 │ └── package_service.py # 快递状态流转服务 ├── templates/ │ ├── user/ │ └── admin/ └── static/ ├── css/ └── js/view层只负责接收请求、调用服务、返回响应或模板具体业务逻辑放在service层模型里只放数据定义和简单的辅助方法。这样分工的好处是短信发送逻辑变了不用动视图函数快递状态流转加了新状态不用改页面代码的每个模块都只做好一件事。很多Flask教程喜欢把所有东西堆在一个文件里演示是方便但项目到了一定规模就难以维护了。4.4 用Django重构这个项目的对比与取舍虽然我最终用Flask实现了这套系统但还是想聊聊如果换成Django会是什么样。Django自带的后台管理确实是这个项目的一大诱惑快递单表、取件记录表直接注册到Django Admin马上得到一个可用的管理界面。Django的ORM也更强关联查询和聚合统计写起来比SQLAlchemy更简洁。比如搞定“每天取件量统计”这类报表Django的annotate和Count可以一个语句搞定。但是Django也有让这个项目变重的地方。Django默认的项目结构是project加app模式快递管理、用户管理、取件记录可能被拆成好几个应用应用之间的依赖关系会让新手绕晕。Django的迁移系统虽然强大但模型一改就得生成迁移文件对这个规模的项目来说有点大炮打蚊子的感觉。另外Django的模板语言和Admin后台自定义的复杂度比Flask高不少如果想要高度定制化后台界面学习曲线会更陡。从实际开发体验来看Flask更像一把精密的小刀你完全控制刀柄的形状和刃口的角度Django更像一套包含厨房的厨具什么都备好了但你想用自己那把顺手的刀时还得腾地方。我最终选择Flask也是因为它让我能把取件码生成、短信推送、状态流转这些最有业务特色的部分干净利落地实现出来。如果重新来一次我还是会用Flask但这个选择的前提是你愿意花时间管理项目结构而不是滥用Flask的自由度写出一个巨型单文件应用。5. 常见问题与坑位排查5.1 用户端常见问题速查表这套系统上线后我整理了一份问题速查表方便驿站老板自己和用户沟通。最常见的问题排在前面可以节省大量答疑时间。问题现象排查思路解决方案用户收不到短信检查短信发送接口的返回码是否是签名或模板审核未过登录短信平台后台查看发送日志和余额提示取件码无效可能是输错码或者已经取过件状态变成已取件核对手机号确认该快递的当前状态登录后看不到快递确认注册手机号是否和快递单录入的手机号完全一致前后不要有空格让用户用快递单上的手机号重新注册或登录快递取件后记录查不到确认取件记录是否有插入检查数据库事务是否提交查看pickup_record表确认有无对应记录5.2 部署和运行中的连接异常开发环境跑得好好的一到部署就出幺蛾子这是Web开发的老传统了。最常见的是数据库连接报错。如果你是照我的流程先在本地用SQLite开发部署时切到MySQL最容易遇到的就是时区不对导致取件时间少了8小时。解决方案是在MySQL连接串里加charsetutf8mb4处理中文编码问题在应用配置里设置SQLALCHEMY_ENGINE_OPTIONS连接池参数。SQLALCHEMY_DATABASE_URI mysqlpymysql://root:passwordlocalhost/express_db?charsetutf8mb4 SQLALCHEMY_ENGINE_OPTIONS { pool_size: 10, pool_recycle: 3600, pool_pre_ping: True, }pool_pre_ping这个参数很多人会忽略它的作用是每次从连接池取连接之前先探活避免MySQL服务端因为长时间不活动断开连接后应用还持有失效连接报MySQL server has gone away。这个问题在快递驿站这种用着用着一整天不怎么高流量的场景下特别容易出现探活参数加上了就基本不会再遇到。5.3 管理员操作上的提醒系统部署到驿站实际使用后有几个管理员操作习惯上的注意事项。入库时快递单号和取件码一定要确认无误再提交因为取件码是系统自动生成的一般不会错但单号手滑输错会导致用户收到短信却查不到快递。这时候如果短信已经发出去了正确的处理是在后台修改单号而不是删掉重录因为删掉重录会产生一条新记录新取件码发出去的短信和用户手上已有的短信就对应不上了。另一个提醒是关于取件验证时的手机尾号。虽然系统支持连续取件时只验证一次手机号但实际运营中我发现有些用户会一次帮邻居取好几件。这种情况下手机尾号匹配的机制天然支持不会出错。但如果遇到某个人取了好几个不同手机号的快递就要每次核对清楚宁可多问一句也不要图快漏验。驿站里最贵的不是系统而是信任冒领一单的损失远超多花几十秒核对的时间。6. 项目后续扩展的三个方向这套取件管理系统做完之后我和驿站老板聊了很多他们还想加的功能结合我自己的观察有三个扩展方向最值得动手。第一个是数据大屏驿站门口挂一块屏幕实时显示今天入库量、取件量、待取数量、超24小时未取件提醒。技术上直接用Flask的模板定时刷新或者加一个简单的WebSocket推送就能做视觉效果很好还能提升驿站的专业形象。第二个是微信小程序端把用户端的查询和取件通知搬到微信小程序里比短信更直观也更省钱。Flask后端可以做成一个纯粹的REST API服务小程序负责界面和交互前后端通过JSON通信这个方向我目前正在做。第三个是滞留快递的主动提醒。现在系统只是标记滞留但实际操作中驿站希望系统能自动给滞留超过48小时的快递再次发短信提醒。实现逻辑很简单后台加一个定时任务每天固定时间查询所有状态为NOTIFIED且入库时间超过48小时的快递统一触发一次提醒短信。定时任务可以用APScheduler库挂在Flask应用里也可以用操作系统的crontab定时跑一个Python脚本取决于你的部署环境。这个功能上线后驿站货架周转率能提升不少用户也觉得服务更贴心。最后分享一个我实际操作中的体会。做这套系统时最难的不是技术而是把驿站真实业务抽象成代码里的状态和数据流。一开始我只盯着表结构和路由后来意识到每一个功能背后都是一个真实场景比如用户取了三个快递但只报了一个码比如货架上同一位置出现了两件单号极像的包裹。把这些边界情况想在前面后面的开发和维护都会顺畅很多。如果你也正在做一个类似的信息管理系统建议先花几天时间泡在现场看流程再打开PyCharm写代码这一半的坑就已经填上了。
返回列表