
1. 项目背景与整体设计思路接这个项目之前客户那边的生产车间里已经有十六台焊接机器人和四台搬运机器人专门做汽车挡泥板的生产。挡泥板这东西听着不起眼却是汽车底盘防护的关键件产线上的机器人每天三班倒大概要产出两千件成品。问题不在于设备本身而在于设备的管理方式——台账靠纸质记录、维修靠电话通知、产量靠人工统计、质量数据散落在各台工控机里。老板想搞一套管理系统把设备状态、生产工单、质检数据、维修记录全部拉通于是就有了这个基于Python的车辆挡泥板机器人工厂管理系统。技术上选型很明确主框架用Django边路用Flask都是Python生态里非常成熟的Web框架。Django负责整个业务管理后台包括设备台账、工单管理、排产计划、质量追溯、报表统计这些重型业务。Flask则跑在现场的工控机和边缘网关盒子上面专门做机器人运行数据的采集、状态上报和接口转发它足够轻、足够灵活装在一台四核小主机上也不占什么资源。这套系统能解决的实际问题简单归纳就是三件事设备状态看得见、生产进度说得清、质量异常查得准。对车间主任来说打开电脑就能看到每台机器人在干什么、当前工单完成到多少件对维修工来说机器人一报故障系统自动生成维修工单并通知到人对质量员来说扫描一个产品二维码就能追溯到是哪台设备、哪个班次、什么工艺参数下生产的。这套系统比较适合两类人去参考一类是工厂里做设备管理或信息化推进的工程师想搞清楚数字化管理系统的实际落地路径另一类是Python开发人员尤其对Django和Flask组合架构感兴趣的同学。后面我会把整个系统的设计思路、核心模块、数据库建模、采集服务实现、以及上线过程中踩过的坑都拆开讲一遍有些内容是用钱和时间换来的教训希望帮大家少走弯路。1.1 这条产线为什么需要一套管理系统先说一个我调研时的场景车间里有一台机器人的焊枪冷却水流量偏低系统也报警了但设备维护工没在跟前。这种报警会在机器人控制柜的触摸屏上闪烁如果操作工刚好在产线另一头就得等巡检人员走到跟前才能发现。传统的管理模式完全靠人巡、靠电话、靠交接班记录本信息是断裂的。老板就算有心想抓设备综合效率手里也拿不出靠谱的数据因为整条产线的设备种类杂、品牌多每台机器人都有自己的一套通讯接口和日志格式人工汇总门牌号都记不住。而挡泥板产线还有一个特点机器人焊接节拍很快单件加工时间非常短一旦设备出问题停线几十分钟就能积压一大片在制品。管理者需要实时掌握产线的运行状态及时调度补产。这套管理系统就是把这些分散的信息统一收口先解决数据有没有的问题再解决数据准不准的问题最后才是数据怎么用的问题。1.2 技术选型为什么是Django Flask而不是二选一很多人会问都是Python Web框架为什么不用一套Django干到底或者干脆全用Flask这个问题的答案其实取决于系统各部分的运行环境差异。Django的优势在于全家桶——ORM、Admin后台、用户认证、权限管理、表单处理、自动化迁移这些能力对于一个后台管理系统来说全是刚需能省掉大量重复造轮子的时间。但Django也有它不太合适的地方它的运行依赖比较重部署一套完整环境要安装的第三方包多启动内存占用高对于现场工控机这种资源紧凑的环境来说并不理想。Flask则恰恰相反它核心只有一个路由分发和WSGI处理本身不绑定数据库、不做权限体系、不强制定任何项目结构你想怎么组织都行。把Flask跑在现场边缘网关里配合Gunicorn或者简单的进程守护一个采集服务从开发到部署可以控制在非常小的体积内。而且Flask写REST接口拿手机器人厂商给的SDK和协议调用逻辑封装成独立的采集微服务接口简单出了问题也好排查不影响主系统的稳定性。另外还有一点很实际这套系统的采购方可能是分批付款的Django后台属于管理端通常先上线验收采集端属于现场数据基础设施要跟着设备改造逐步推进。两个框架解耦之后开发计划和验收节奏可以各走各的不会互相牵制。如果未来某个环节需要换成FastAPI或者Go的采集服务也不会波及到Django主系统的代码。1.3 系统整体架构与模块划分从部署结构上说这套系统分三层。最上层是Django管理后台部署在公司内网的一台服务器上数据库采用MySQL缓存用Redis主要面向车间管理、工艺、质检、设备维修这些角色。中间层是Flask采集服务集群分别部署在各条产线的边缘网关或者工控机上向下对接每台机器人的控制器和PLC向上通过HTTP API把数据写入Django的数据库或Redis队列。最底层就是产线设备层包括焊接机器人、搬运机器人、PLC、传感器和质检工位。整体架构并不复杂核心是理清数据流向设备状态数据从底层往上走管理指令从上层往下走两边在Django主系统的业务逻辑里交汇。模块划分上Django侧包括设备档案管理、工单排产管理、生产报工管理、质检追溯管理、维修保养管理、系统权限与操作日志。Flask侧包括设备心跳上报、实时状态转发、报警事件采集、机器人程序版本记录和参数回读。两边通过一套简单的鉴权Token进行通信避免管理后台直接暴露在现场设备网络里。2. 核心业务模块与数据库建模详解系统做得好不好一半看业务逻辑设计一半看数据库建模。历史上很多工厂管理系统最后沦为僵尸系统原因往往不是功能不够而是业务流程没有梳理清楚数据库里存了一堆没法支撑业务的字段界面做完了才发现设计跑偏。所以这个项目的数据库建模阶段花的时间比写代码时间更长我挨个车间跟了三个班次才把每个业务角色的真实工作流程摸清楚。2.1 设备管理模块机器人台账与生命周期状态设备是产线的核心资产建模的时候要把一台机器人从进场到报废的整个生命周期管起来。我设计的模型里机器人设备表是最基础的一张表除了设备编号、名称、型号这类基本属性之外还重点加了几个对工厂管理特别有用的字段所属产线、安装位置、投用日期、运行状态、最后心跳时间。设备表的状态字段不搞模糊概念只定义四个值——online在线运行、offline离线、fault故障、maintain保养/维修中。这个状态不是人工在后台改的而是由Flask采集服务根据机器人心跳和报警信号自动更新的人工只做确认和收尾操作。设备保养记录单独建表关联设备ID、保养类型、保养人员、保养日期和下次保养日期后台可以设定提醒规则接近保养周期就自动在首页看板弹提醒。还有一个容易被忽略的关键字段是设备IP和通讯协议类型。不同品牌的机器人通讯方式不一样有的支持OPC UA有的只开放Modbus TCP有的厂家提供HTTP接口的SDK。设备表里存下这些参数Flask采集服务启动时才能根据设备类型自动选择合适的通讯插件。2.2 工单与排产逻辑生产进度的可视化管理工单是整个生产流程的主线从下达生产指令到最终完工入库每一步状态都要有据可查。工单表的核心字段包括工单号、挡泥板型号、计划数量、已完工数量、计划开始/结束时间、优先级、状态。工单状态机我设计成五个阶段待排产pending、已下发released、生产中in_progress、已完工completed、已取消cancelled每个状态之间的流转在Django里用独立函数控制不做自由跳转避免数据被误操作搞乱。排产逻辑分配给车间计划员在Django后台完成。计划员按交付日期倒排生产计划选择对应产线系统自动校验设备当前状态和生产日历防止把工单排到正在维修的设备上。车间班组长在自己的平板电脑上能看到当班工单列表点击开始生产后工单状态自动切到生产中同时系统给对应的机器人下发生产配方信息。生产过程中每完成一件合格品质检工位扫描条码自动触发报工已完工数量实时累加。2.3 质量追溯挡泥板检测数据如何关联到设备和批次挡泥板的质量追溯在焊接工艺中尤其重要。焊道偏移、焊缝气孔、飞溅过多这些问题如果不在当天发现后续返工成本很高。质量模块我做了两级追溯批次级和单件级。每批挡泥板对应一个批次号批次号关联工单号、设备号、操作班组、工艺参数版本和原料批号。质检员抽检时扫批次号录入抽检结果不良品数量直接扣减工单合格数量。单件追溯则靠二维码实现。每件挡泥板从产线下来时打码码中包含生产日期、班次、工位号、工单号序列。质量异常时扫这个码就能查到当时焊接机器人的电流、电压、送丝速度、气体流量这些关键参数的最近记录。这些参数数据量很大如果全部实时写MySQL压力太大所以设计成定时汇总详细参数保存到独立的汇总表按工单维度归档页面展示时按需查询。2.4 核心数据表结构与Django模型实现示例下面我把设备表和工单表的Django模型代码贴出来这是实际项目中精简后的版本保留了核心逻辑。模型定义遵循几个原则所有业务表都有created_at和updated_at需要做追溯的字段都设置db_index状态字段用短字符串常量而不是数字直接提高代码可读性。from django.db import models class Device(models.Model): STATUS_CHOICES ( (online, 在线运行), (offline, 离线), (fault, 故障), (maintain, 维护中), ) code models.CharField(max_length32, uniqueTrue, verbose_name设备编号) name models.CharField(max_length64, verbose_name设备名称) device_type models.CharField(max_length32, verbose_name设备类型) line models.CharField(max_length32, verbose_name所属产线) position models.CharField(max_length64, verbose_name安装位置) ip_address models.GenericIPAddressField(verbose_name设备IP) protocol models.CharField(max_length16, defaultmodbus, verbose_name通讯协议) status models.CharField(max_length16, choicesSTATUS_CHOICES, defaultoffline, verbose_name运行状态) install_date models.DateField(nullTrue, blankTrue, verbose_name投用日期) last_heartbeat models.DateTimeField(nullTrue, blankTrue, verbose_name最后心跳时间) remark models.TextField(blankTrue, verbose_name备注) class Meta: db_table device verbose_name 设备档案 indexes [ models.Index(fields[status, line]), ] def __str__(self): return f{self.code}-{self.name}class WorkOrder(models.Model): STATUS_CHOICES ( (pending, 待排产), (released, 已下发), (in_progress, 生产中), (completed, 已完工), (cancelled, 已取消), ) order_no models.CharField(max_length64, uniqueTrue, verbose_name工单号) product_model models.CharField(max_length64, verbose_name挡泥板型号) plan_qty models.IntegerField(verbose_name计划数量) completed_qty models.IntegerField(default0, verbose_name合格完工数量) defect_qty models.IntegerField(default0, verbose_name不良品数量) priority models.IntegerField(default0, verbose_name优先级) plan_start models.DateTimeField(verbose_name计划开始时间) plan_end models.DateTimeField(verbose_name计划结束时间) actual_start models.DateTimeField(nullTrue, blankTrue, verbose_name实际开始时间) actual_end models.DateTimeField(nullTrue, blankTrue, verbose_name实际结束时间) status models.CharField(max_length16, choicesSTATUS_CHOICES, defaultpending, verbose_name状态) device models.ForeignKey(Device, nullTrue, blankTrue, on_deletemodels.SET_NULL, verbose_name生产设备) created_by models.ForeignKey(auth.User, on_deletemodels.PROTECT, verbose_name创建人) created_at models.DateTimeField(auto_now_addTrue, verbose_name创建时间) class Meta: db_table work_order verbose_name 生产工单 indexes [ models.Index(fields[status, plan_start]), ] def __str__(self): return self.order_no提示设备名称建议包含品牌和型号比如FANUC R-2000iC/210F这样维修工看到设备列表就能直接判断配件型号不用再去翻档案柜。字段设计上有几个小心思工单关联设备的ForeignKey用了SET_NULL而不是CASCADE因为工单是生产追溯的重要凭证即使设备从系统里删除工单记录也必须保留设备信息和历史关联。模块间尽量不通过跨表外键互相拉扯而是用查询条件关联方便后续业务扩展时不容易被表结构卡住。3. Django主系统的业务实现与关键代码Django部分我的组织方式是按业务域建App一个App管一组聚合的业务这样不会出现一个App里堆几百个文件的情况。这个项目拆了四个Appaccounts用户与权限、devices设备与维修、production工单与排产、quality质检与追溯。3.1 项目管理结构与App创建创建App这个动作本身没什么好说的一条命令的事情但App的边界划分是真正考验经验的地方。我见过一些项目把所有模型都放在一个App里结果model.py文件超过两千行谁都不敢动。这个项目的划分思路是设备域里只放设备本身、通讯参数、维修保养记录不掺生产计划生产域里只放工单、排产、报工质检域只管检验记录和质量分析。跨域的数据联动不靠外键强关联而是通过业务服务层调用代码里保持低耦合。python manage.py startapp devices python manage.py startapp production python manage.py startapp quality python manage.py startapp accountsApp创建之后再逐个编写模型、视图、序列化和URL路由。Django的URL分发机制天然适合把各业务域的API分开管理每一个App里建一个urls.py主urls.py再统一include接口路径一目了然比如/devices/api/、/production/api/。3.2 权限管理与登录认证的落地工厂管理系统的角色权限和普通互联网项目不一样操作人员是固定的内部员工角色类型也相对稳定不需要复杂的社交登录和验证码体系。我用Django内置的User模型配合Group做角色控制细分了五类角色系统管理员、车间计划员、班组长、质检员、维修工。每种角色在Django Admin里勾选对应的Group权限视图层面再用permission_required装饰器做接口防护。登录认证方面后台管理页面保持传统的Session认证因为使用者是内部员工浏览器操作方便最重要。Flask采集服务则不走Session采用Token认证方式在Django里生成一个长期有效的API Token下发给边缘网关Flask请求时在Header里带上这个TokenDjango侧用一个中间件校验。这样做的好处是采集服务和主系统之间的通讯不依赖登录状态即使现场工控机长时间没有交互也不用担心会话过期。# Django中间件示例校验Flask采集端的API Token from django.http import JsonResponse from django.conf import settings class ApiTokenMiddleware: def __init__(self, get_response): self.get_response get_response def __call__(self, request): if request.path.startswith(/api/collect/): token request.headers.get(X-Api-Token) if token ! settings.COLLECT_API_TOKEN: return JsonResponse({code: 401, msg: invalid token}, status401) return self.get_response(request)部署时把COLLECT_API_TOKEN配置在环境变量里不要写死在settings.py更不要提交到代码仓库。这个习惯我从一开始就坚持后面换服务器或者多人协作开发时省了很多麻烦。3.3 Django查询优化避免报表页面卡死的经验系统上线后最容易被吐槽的就是报表页打不开。挡泥板产线每天产生几万条报工和检测记录如果查询写得粗糙统计页面三秒都转不完。这里给两个最实用的优化经验。第一关联查询务必使用select_related和prefetch_related避免N1查询。之前我排查过一个设备列表页面卡顿的问题页面显示五十台设备每台设备要查最近一条维修记录结果执行的SQL数量是五十加一次数据库压力全浪费在这种低效查询上了。用了Prefetch之后一次查询把五十条维修记录全部带出来页面响应时间从1200毫秒降到80毫秒。第二报表统计别在Python里循环算用聚合函数一次性算完。统计每个设备当月的产量放在Django ORM里就是一条annotate加Count/Sum的聚合语句让数据库把结果算好返回而不是在Python里写循环然后一条条执行SQL。这个习惯在数据量小的时候看不出区别数据量上来之后性能差距是数量级的。4. Flask采集服务与机器人数据对接如果说Django部分是管理系统的大脑那Flask采集服务就是神经末梢。它直接面对产线上各种品牌的机器人承受的是恶劣的现场环境、复杂的协议差异和不稳定的网络这部分写不好整个系统的数据基础就是空中楼阁。4.1 机器人数据采集的几种常见方式工业机器人对外通讯一般有几种方式底层协议如Modbus TCP、OPC UA厂商私有协议如FANUC的FOCAS、KUKA的RobotSensorInterface还有部分新设备提供RESTful HTTP接口。这个项目里的机器人品牌比较杂焊接机器人有FANUC和ABB搬运机器人有KUKA一时间没法统一协议。最后的方案是做了一个采集适配层每一种协议封装成一个独立的采集类对外暴露统一接口上层调度逻辑不需要关心设备具体是哪个品牌。Modbus TCP协议适合读PLC里中转的机器人状态字比如运行/停止/报警/自动模式这些开关量。FANUC机器人可以通过FOCAS接口读取当前坐标、伺服电流、程序名这些生产数据。OPC UA则是未来的统一方向新采购的设备基本都会支持。我建议工厂在规划设备采购时尽量要求供应商开放OPC UA接口后续做数据采集可以省去非常多的适配工作。4.2 Flask采集服务的核心流程采集服务的核心逻辑可以概括为三件事定时轮询、状态判断、数据上报。工控机上部署的Flask服务启动时读取设备清单为每台设备启动一个采集线程采集线程按照设定的周期一般是三秒到五秒向机器人控制器发起通讯请求拿到数据后立即解析成统一的JSON格式然后通过HTTP POST上报到Django的采集接口。心跳上报不同于普通数据上报它专门用来判断设备和采集服务是否还活着。Flask服务每三十秒向Django发送一次心跳包Django收到后更新设备表的last_heartbeat字段。管理后台看到设备状态变成离线时先查last_heartbeat离当前时间多久就能快速区分是设备本身断电了还是通信链路断了。# Flask采集服务设备状态上报示例 from flask import Flask, jsonify, request import httpx import threading import time app Flask(__name__) COLLECT_API_URL http://server.internal:8000/api/collect/device_status/ API_TOKEN your-token-here def collect_and_report(device_info): while True: try: status read_robot_status(device_info) payload { device_code: device_info[code], status: status[status], program: status.get(program, ), ctime: time.time() } resp httpx.post( COLLECT_API_URL, jsonpayload, headers{X-Api-Token: API_TOKEN}, timeout5 ) except Exception as e: log_error(device_info[code], str(e)) time.sleep(device_info.get(interval, 5))注意这里每一台设备一个线程的做法仅适用于设备数量几十台的规模如果未来设备量扩大到几百台需要引入异步IO协程方案否则线程数会耗尽工控机资源。我在这个项目里踩了这个坑的雏形现场一台四核工控机跑二十台设备线程CPU占用率稳定在百分之六十左右勉强能用但规模扩大之前必须重构。4.3 采集库与业务库的数据同步策略Flask采集服务采集到的数据如果每一条都直接写MySQL数据库写入压力会非常大而且现场工控机的网络并不一定稳定数据库连接断掉时数据就会丢。这个项目采用了两级缓存的策略Flask服务本地先把采集结果写到SQLite数据库里作为缓冲同时尝试推送到Django主系统的Redis队列里Django后台有一个定时任务每隔一段时间从Redis队列批量把数据写入MySQL写入成功的消息才从队列里移除。这套策略的好处是扛得住网络抖动。有一次客户现场检修网络交换机连续重启了好几次采集服务本地SQLite里存了将近两个小时的数据网络恢复后Redis队列一次性补推成功主库没有任何数据缺失。如果用直写方案这种情况大概率会丢数据或者生产一堆重试异常。数据同步的补偿机制是整个系统稳定性的重要保障这一点投入的代码量看似多了但换来的是少接半夜的故障电话。5. 典型业务场景实操流程写后台管理系统不能只看功能清单要看实际业务流程跑得顺不顺。这块我挑三个最典型的场景完整走一遍流程包括操作人员是谁、界面点了什么、系统后台发生了什么方便读者参考映射到自己的项目里。5.1 场景一从创建工单到机器人上线的完整流程车间计划员登录Django后台进入生产管理-工单管理页面点击新建工单。填写挡泥板型号、计划数量、计划开始与结束时间选择优先级后保存。此时工单状态为待排产。计划员在排产列表里选中这张工单系统自动列出当前空闲且状态为在线的设备指定其中一台焊接机器人点击下发工单状态变为已下发。班组长在车间的平板电脑上刷新工单列表看到当班任务后点击开始生产。系统前端调用后端接口后端把工单状态修改为生产中记录实际开始时间同时生成一个生产批次号。机器人操作工从设备触摸屏上加载对应程序开始生产。生产过程中质检工位每完成一件扫描一次系统调用报工接口当前工单的completed_qty自动加一。当completed_qty达到plan_qty时系统自动把工单状态改为已完工记录实际结束时间并在看板上亮起完成信号。5.2 场景二机器人报警与维修工单的处理闭环焊接机器人向Flask采集服务上报状态为故障Flask把报警事件推送到Django。Django后台收到报警事件后先从设备表里查出这台设备对应的维修负责人然后自动生成一条维修工单同时向维修工手机端推送通知。维修工在手机上看到报警内容到现场排查处理后在系统里填写故障原因、处理措施和配件更换记录提交关闭维修工单。这个闭环里最值得注意的设计是报警等级分三级低级别报警只记录日志不生成工单中级别报警生成工单但不通知高级别报警既生成工单又实时推送。如果所有报警都推送维修工一天要被骚扰十几次系统很快就会被弃用。报警阈值和等级规则在后台配置化每个设备类型可以单独设置。5.3 场景三质量异常时的追溯查询质检员在生产过程中发现一批挡泥板焊缝气孔率异常这时候需要在质量模块里发起追溯。在追溯查询页面输入批次号或者扫描单件二维码系统返回该批次关联的工单信息、生产设备、操作班组、工艺参数版本以及这台机器人在这段时间内的关键参数曲线。在参数数据基础上质检员可以结合焊接电流、送丝速度是否偏移来判断是参数设定问题还是设备机械问题。这个场景对系统性能有一点要求因为参数曲线查询背后可能是几千条实时采样数据前端展示需要做缩略处理。我的做法是后端在返回给前端之前先做降采样把几千个点压缩成几百个展示点既保证了趋势可见又不会把浏览器撑爆。数据采样保留时间设定为十二个月超过保留期的自动归档到历史表控制主表体量。6. 常见问题与排查技巧实录系统从开发到上线再到稳定运行中间遇到的坑比想象中多得多。我把最有代表性的问题和排查思路整理成了表格这些内容也是整个项目最值钱的经验所在。6.1 高频问题速查表现象可能原因排查思路与解决方法报表统计页面响应缓慢关联查询造成N1循环内执行SQL用select_related/prefetch_related优化改聚合查询设备状态长时间显示离线采集线程崩溃或网络中断检查Flask服务日志看设备心跳时间重启采集服务并确认守护进程自动拉起机器人数据断档半小时边缘网络抖动Redis队列堆积检查本地SQLite缓冲区数据网络恢复后观察补推是否完成工单状态卡在生产中不更新报工接口异常或前端未同步刷新查看报工接口日志检查工单completed_qty是否达到plan_qty两台框架服务混在一起时session冲突Django和Flask共用同一个浏览器session明确服务边界Flask服务不走Session改用API Token部署后页面报500错误ALLOWED_HOSTS未配置或SECRET_KEY未设置检查Django settings环境变量查看DEBUG模式和错误日志现场工控机与服务器时间不一致时钟偏移未同步配置NTP定期同步采集数据统一用UTC时间戳存储6.2 现场排查实录一次诡异的设备离线问题上线第二周客户反馈车间里有一台ABB机器人在管理后台一直显示离线但在机器人控制柜触摸屏上看设备运行完全正常。我远程登录Flask采集服务所在工控机先看采集进程还在不在结果进程还活着。接着看采集日志发现机器人地址连通性测试一直超时。在工控机上直接ping机器人控制柜IP通的再用Modbus工具测试端口却连不上。最后定位到问题根源机器人的通讯模块在长时间运行后进入了一种半死机状态以太网口在物理层是通的但协议栈不响应。把机器人控制柜的通讯模块断电重启后采集恢复正常。这类问题靠写代码解决不了必须让现场运维在巡检表里加上一条每星期重启一次通讯模块。遇到类似情况先别急着怀疑自己的代码把链路里每一段的物理状态都排查一遍很多系统问题其实是设备硬件问题。还有一个容易忽略的坑Django的时区设置。采集服务上报时传的是时间戳Django的settings.py里TIME_ZONE设置为UTCUSE_TZ设置为True这样所有设备上报的时间在数据库里统一以UTC存储展示时再转换为本地时间。如果一边用UTC一边用本地时间混着来追溯时间线会乱得一塌糊涂。这类问题不会当场暴露往往在事后分析数据时才致命务必从一开始就统一口径。6.3 部署过程中的依赖与版本管理经验这个项目同时在服务器和现场工控机上跑两个环境的Python版本和系统环境差异很大依赖管理做不好就是灾难。我强烈建议用conda或者虚拟环境把Python运行时隔离起来不要直接用系统自带的Python环境装包。Django项目建议锁定Python 3.10左右的版本Django 4.2 LTS版本长期维护稳定性好适合企业项目。Flask采集服务则用更轻的依赖组合能少装就少装现场工控机常常没有外网离线安装依赖包这件事非常折磨人。我踩过一个典型的坑现场一台工控机是精简版Linux系统缺少一堆底层编译依赖pip install第三方包时经常编译失败。后来我把所有依赖包提前下载成whl文件连同部署脚本一起打包拷贝到现场离线安装才彻底解决了这个问题。做工厂项目永远假设现场网络环境是不可靠的依赖包、安装介质、部署文档这三样东西必须离线可用。7. 系统后续扩展方向与个人收尾体会这套系统上线试运行了一个多月月底盘点时客户发现最大的变化是数据不用再对账了——产量数据和质检数据在系统里自然闭环设备故障的平均响应时间从原来的两个多小时压缩到四十分钟以内。老板甚至主动要求加一个车间大屏展示页面把产线状态和当日产量投到车间墙上这其实是看得见的效果倒逼出来的需求。从扩展角度讲这套Django Flask的架构向微服务演进也比较顺畅。如果后续要接ERP或者MES可以在Django侧直接开发接口或者把采集服务独立成更专业的边缘计算服务增加边缘端的实时质量判断能力。如果要对接可视化大屏Django提供数据API前端用任意图表框架都行我建议优先考虑集成国内成熟的大屏组件开发者可以少花很多时间在图表适配和浏览器兼容性上。从个人实际经验角度说几句。我体会最深的一点是工业软件开发七成功夫在弄清楚现场业务三成功夫在写代码。你写的每一张表、每一个状态字段背后都对应着车间里一个具体的人和他每天的工作习惯。多蹲几天产线比多看几篇技术文档管用得多。技术选型上Django和Flask的组合不是什么高大上的方案但胜在分工清楚、各取所长、容易维护对于中小型工厂的管理系统来说是非常务实的搭配。最后分享一个小建议整个部署过程中一定要把Django的SECRET_KEY、数据库密码、采集服务的API Token这些敏感信息全部放在环境变量或者单独的配置文件中任何情况下都不要提交到代码仓库。我在项目交付后做代码审查时发现过不止一次私钥泄露的情况严重的话可以直接通过Django的SECRET_KEY伪造会话登录后台。这个习惯越早养成越好它不花什么成本但关键时刻能帮你保住整个系统。