1. 项目概述
这个基于Django框架开发的实验室信息管理系统(LIMS)是一个面向科研机构、高校实验室的综合性管理平台。我在实际开发过程中发现,传统实验室管理普遍存在数据分散、流程混乱的问题,而这个系统通过模块化设计解决了样本追踪、设备管理、人员考核等核心痛点。
系统采用Python 3.8+Django 3.2的技术栈,前端使用Bootstrap 5实现响应式布局。特别值得一提的是,我们针对实验室场景优化了批量导入功能,实测可支持单次500条以上样本数据的快速录入,比传统Excel管理效率提升约60%。
2. 系统架构设计
2.1 技术选型考量
选择Django框架主要基于三个实际需求:
- 实验室管理涉及复杂权限控制(学生/教师/管理员三级权限)
- 需要快速开发CMS类功能(Django自带admin后台)
- 后期可能对接仪器设备API(Django REST framework扩展性强)
数据库选用PostgreSQL而非MySQL,是因为实验室数据具有:
- 高一致性要求(实验记录不允许丢失)
- 复杂查询需求(多条件筛选样本)
- 地理空间数据支持(部分实验室需记录设备位置)
2.2 核心模块划分
系统包含6个主要模块:
- 样本管理:条形码生成+生命周期追踪
- 设备管理:预约日历+使用记录
- 耗材库存:低库存预警+采购流程
- 人员管理:权限组+绩效考核
- 数据看板:可视化实验数据
- 文档中心:SOP文件版本控制
提示:实际部署时建议将文档中心模块单独配置存储卷,避免系统升级导致文件丢失
3. 关键功能实现
3.1 样本追踪系统
核心难点在于解决样本的"父子关系"(如分装、合并)和状态流转。我们采用Django Model的有限状态机设计:
python复制class Sample(models.Model):
STATUS_CHOICES = (
('received', '已接收'),
('processing', '处理中'),
('stored', '已存储'),
('disposed', '已处置')
)
current_state = FSMField(default='received', choices=STATUS_CHOICES)
@transition(field=current_state, source='received', target='processing')
def start_processing(self):
"""样本开始处理时自动记录操作人"""
self.processed_by = request.user
3.2 设备预约冲突检测
在设备预约模块中,我们实现了基于时间重叠检测的冲突判断算法:
python复制def check_availability(equipment, start_time, end_time):
conflicts = Reservation.objects.filter(
equipment=equipment,
end_time__gt=start_time,
start_time__lt=end_time
)
return not conflicts.exists()
实测发现需要额外考虑时区问题,建议在settings.py中明确设置:
python复制USE_TZ = True
TIME_ZONE = 'Asia/Shanghai'
4. 部署优化实践
4.1 性能调优方案
通过Django Debug Toolbar分析发现,样本列表页存在N+1查询问题。优化方案:
- 使用select_related优化外键查询:
python复制samples = Sample.objects.select_related('owner', 'location')
- 对分页结果添加缓存:
python复制from django.core.cache import cache
def get_sample_page(page_num):
cache_key = f'samples_page_{page_num}'
result = cache.get(cache_key)
if not result:
result = list(samples[page_num*50:(page_num+1)*50])
cache.set(cache_key, result, timeout=3600)
return result
4.2 安全防护措施
实验室系统需特别注意数据安全:
- 密码策略:强制8位以上+特殊字符
python复制AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {'min_length': 8}
}
]
- 操作日志审计:
python复制class OperationLog(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
action = models.CharField(max_length=200)
ip_address = models.GenericIPAddressField()
timestamp = models.DateTimeField(auto_now_add=True)
5. 常见问题排查
5.1 文件上传失败
常见原因及解决方案:
-
文件大小超限:调整nginx配置
code复制client_max_body_size 20M; -
文件名含中文:添加中间件处理
python复制from urllib.parse import quote class ChineseFilenameMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if 'filename' in request.FILES: request.FILES['filename'].name = quote(request.FILES['filename'].name) return self.get_response(request)
5.2 定时任务异常
使用Celery时遇到的典型问题:
-
任务堆积:建议配置优先级队列
python复制CELERY_TASK_ROUTES = { 'tasks.high_priority': {'queue': 'high'}, 'tasks.low_priority': {'queue': 'low'}, } -
结果丢失:启用Redis作为结果后端
python复制CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
6. 源码结构说明
项目采用标准Django项目结构,但增加了两个特殊目录:
code复制/lab_management
/custom_migrations # 存放数据迁移脚本
/fixtures # 初始测试数据
关键配置文件:
settings/env.py:环境变量管理requirements/dev.txt:开发依赖scripts/backup.sh:数据库备份脚本
在开发过程中,我们特别注重保持代码的可维护性。每个app都严格遵循单一职责原则,视图函数代码行数控制在150行以内。对于复杂业务逻辑,我们使用services层进行封装:
python复制# samples/services.py
class SampleService:
@classmethod
def create_batch_samples(cls, data_list):
"""处理批量创建样本的复杂逻辑"""
with transaction.atomic():
samples = [Sample(**data) for data in data_list]
Sample.objects.bulk_create(samples)
cls._generate_barcodes(samples)
cls._send_notifications(samples)
这种架构设计使得后期新增样本类型时,只需继承SampleService类并重写相关方法即可,大大降低了维护成本。实际项目中,这种设计模式帮助我们仅用2天就完成了COVID样本特殊处理流程的开发。