1. 项目概述:基于Django的生产执行管理系统开发实录
去年参与某制造企业数字化改造项目时,我负责开发了一套生产执行管理系统。这个采用Django+MySQL技术栈的系统,成功将企业原本纸质化的生产管理流程数字化,使订单交付周期缩短了37%。本文将完整还原该系统的开发过程,包含技术选型思考、核心模块实现细节以及上线后踩过的坑。
生产执行系统(MES)作为连接企业ERP与车间设备的关键层,需要处理实时生产数据、协调资源分配、监控质量指标等复杂任务。传统商业软件动辄百万的授权费用让中小型企业望而却步,而我们的开源解决方案在保证核心功能的前提下,将实施成本控制在10万元以内。
2. 技术架构深度解析
2.1 为什么选择Django?
在技术选型阶段,我们对比了Flask、FastAPI等Python框架。最终选择Django主要基于以下考量:
- 开箱即用的Admin系统:内置的admin界面可快速搭建后台管理模块,节省约40%开发时间
- 完善的ORM支持:对MySQL的深度集成简化了复杂查询编写
- 电池全包含哲学:自带的用户认证、会话管理等功能避免重复造轮子
实际开发中,我们通过重写User模型实现了多角色权限体系:
python复制class CustomUser(AbstractUser):
ROLES = (
('OP', 'Operator'),
('SUP', 'Supervisor'),
('ADM', 'Admin')
)
role = models.CharField(max_length=3, choices=ROLES)
department = models.ForeignKey('Department', on_delete=models.SET_NULL, null=True)
def has_perm(self, perm, obj=None):
if self.role == 'ADM':
return True
# 其他权限逻辑...
2.2 数据库设计中的优化技巧
MySQL表结构设计时,我们特别注意了以下几点:
- 索引策略:为高频查询字段(如工单号、产品编号)创建组合索引
- 字段类型选择:使用Decimal代替Float存储精确数值,避免浮点误差
- 分表设计:将操作日志等高频写入数据与主业务表分离
生产计划表的DDL示例:
sql复制CREATE TABLE `production_plan` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plan_code` varchar(32) COLLATE utf8mb4_bin NOT NULL COMMENT '计划编号',
`product_id` int(11) NOT NULL COMMENT '关联产品',
`quantity` decimal(12,3) NOT NULL COMMENT '计划数量',
`start_date` datetime NOT NULL,
`end_date` datetime NOT NULL,
`status` enum('draft','confirmed','completed') COLLATE utf8mb4_bin NOT NULL DEFAULT 'draft',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_plan_code` (`plan_code`),
KEY `idx_product_status` (`product_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
3. 核心功能模块实现
3.1 生产计划动态排程算法
系统核心功能是根据设备能力、物料库存等因素自动生成最优生产计划。我们实现的贪心算法包含以下步骤:
- 获取待处理订单列表(按交付日期排序)
- 检查物料可用量(考虑安全库存)
- 计算设备理论产能
- 分配生产时间段(避免设备冲突)
- 生成可视化甘特图
关键代码片段:
python复制def generate_schedule(orders):
scheduled = []
for order in sorted(orders, key=lambda x: x.due_date):
materials = check_material_availability(order)
if not materials['available']:
continue
equipment = find_available_equipment(order)
if not equipment:
continue
time_blocks = calculate_time_blocks(order, equipment)
if time_blocks:
schedule = {
'order': order,
'equipment': equipment,
'time_blocks': time_blocks
}
scheduled.append(schedule)
update_material_reservation(materials)
return scheduled
3.2 实时数据采集方案
为实现车间数据实时监控,我们设计了两种数据采集方式:
方案A:设备直连(适用于智能设备)
- 通过Modbus TCP协议读取设备状态
- 使用Celery异步任务处理数据流
- 数据采样频率可配置(默认5秒/次)
方案B:人工录入(传统设备)
- 开发移动端H5界面
- 采用WebSocket保持长连接
- 支持离线模式(PouchDB本地存储)
重要提示:实际部署时发现,车间WiFi信号不稳定会导致WebSocket频繁断开。最终我们增加了心跳检测和自动重连机制,并将关键操作改为乐观更新模式。
4. 性能优化实战记录
4.1 数据库查询优化
系统上线初期,生产计划页面加载需要8-12秒。通过以下措施降至300ms内:
- 使用
select_related和prefetch_related减少查询次数
python复制# 优化前(产生N+1查询)
plans = ProductionPlan.objects.all()
for plan in plans:
print(plan.product.name) # 每次循环都查询product表
# 优化后
plans = ProductionPlan.objects.select_related('product').all()
- 添加数据库读写分离配置
python复制DATABASE_ROUTERS = ['path.to.PrimaryReplicaRouter']
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
return 'replica'
def db_for_write(self, model, **hints):
return 'default'
4.2 前端渲染加速
物料管理界面包含大量表格数据,我们采用:
- 虚拟滚动技术(只渲染可视区域DOM)
- Web Worker处理复杂计算
- 本地缓存策略(IndexedDB存储历史数据)
实测数据显示,万级数据量下渲染性能提升6倍。
5. 部署过程中的血泪教训
5.1 定时任务管理
最初使用Linux crontab管理后台任务,遇到两个严重问题:
- 任务重叠执行(前一个任务未完成,后一个已启动)
- 错误日志难以追踪
解决方案:改用Django Celery Beat,并配置:
- 任务幂等性检查
- 任务超时终止机制
- 集中式日志收集(ELK Stack)
5.2 高并发场景应对
月底生产报表生成时,系统出现多次宕机。通过以下改进解决:
- 增加Redis缓存层(减轻数据库压力)
- 实现报表异步生成(Celery+WebSocket通知)
- 添加负载均衡(Nginx轮询多应用实例)
6. 项目成果与扩展思考
系统上线6个月后取得显著成效:
- 生产数据录入时间减少85%
- 物料浪费率下降22%
- 设备利用率提升15%
未来可扩展方向:
- 集成预测性维护(通过设备振动数据分析)
- 增加AR辅助装配功能
- 对接企业微信/钉钉消息通知
开发过程中最大的体会是:工业级软件必须考虑极端场景下的稳定性。比如我们曾遇到某型号扫码枪在高温环境下传输乱码,最终通过增加数据校验和自动重试机制解决。这些实战经验远比书本知识来得珍贵。