1. 项目背景与核心价值
最近在高校做信息化建设调研时发现,大学生心理健康问题已经成为校园管理中不可忽视的一环。传统纸质问卷和人工统计的方式不仅效率低下,更难以实现动态监测和预警。这个基于Django+Flask双框架的心理健康测评平台,正是为了解决这个痛点而生。
平台最大的创新点在于将Python生态中两个最成熟的Web框架优势互补:用Django搭建稳定的后台管理系统,处理用户权限、问卷管理和数据存储;用Flask构建灵活的前端测评模块,实现动态题型加载和实时交互。实测下来,这种架构既保证了系统稳定性,又能满足复杂测评场景的需求。
2. 技术架构设计解析
2.1 框架选型决策
选择Django作为基础框架主要基于三点考虑:
- 自带Admin后台可以快速搭建问卷管理界面
- ORM层对PostgreSQL的良好支持,适合存储结构化测评数据
- 内置的用户认证系统符合高校多角色(学生/辅导员/管理员)需求
而Flask的加入则解决了两个关键问题:
- 动态测评页面需要频繁的AJAX交互(Flask更轻量)
- 不同测评量表需要独立路由和视图逻辑(Flask的Blueprint更适合模块化开发)
2.2 数据库设计要点
核心数据模型采用三层结构:
class Scale(models.Model): # 测评量表元数据 name = models.CharField(max_length=100) description = models.TextField() class Question(models.Model): # 题目库 scale = models.ForeignKey(Scale) text = models.TextField() dimension = models.CharField(max_length=50) # 所属心理维度 class AnswerRecord(models.Model): # 作答记录 user = models.ForeignKey(User) question = models.ForeignKey(Question) score = models.IntegerField() timestamp = models.DateTimeField(auto_now_add=True)特别要注意的是answer_record表设计:
- 采用纵表结构存储答案,便于后续多维分析
- 添加timestamp字段实现纵向追踪
- 建立复合索引(user_id, timestamp)提升查询效率
3. 核心功能实现细节
3.1 动态测评模块
前端采用Vue.js + Flask RESTful API的架构:
// 前端动态加载题目 async function loadNextQuestion() { const res = await axios.get(`/api/scale/${scaleId}/next`); currentQuestion.value = res.data; } // Flask后端处理 @app.route('/api/scale/<int:scale_id>/next') def get_next_question(scale_id): answered = get_answered_questions(current_user.id, scale_id) next_q = Question.query.filter( Question.scale_id == scale_id, ~Question.id.in_(answered) ).first() return jsonify(question_to_dict(next_q))关键实现技巧:
- 使用Redis缓存已答题ID集合,减轻数据库压力
- 题目呈现顺序采用Fisher-Yates洗牌算法随机化
- 前端添加防抖机制防止重复提交
3.2 数据分析模块
采用Pandas进行数据预处理:
def calculate_dimension_scores(user_id): raw_data = pd.DataFrame.from_records( AnswerRecord.objects.filter(user_id=user_id).values() ) # 计算各维度均分 dimension_scores = raw_data.groupby('dimension')['score'].mean() # Z-score标准化 population_mean = AnswerRecord.objects.aggregate(Avg('score'))['score__avg'] population_std = AnswerRecord.objects.aggregate(StdDev('score'))['score__stddev'] normalized_scores = (dimension_scores - population_mean) / population_std return normalized_scores.to_dict()分析算法选型建议:
- 基础分析:频数统计、交叉分析
- 高级分析:K-means聚类识别高危群体
- 预警机制:设置标准差阈值自动触发
4. 安全与隐私保护方案
4.1 数据加密策略
采用双层加密方案:
- 传输层:强制HTTPS + HSTS
- 存储层:敏感字段使用AES-256加密
from cryptography.fernet import Fernet key = Fernet.generate_key() # 存储在环境变量中 cipher_suite = Fernet(key) encrypted_data = cipher_suite.encrypt(b"Sensitive info") decrypted_data = cipher_suite.decrypt(encrypted_data)4.2 访问控制设计
基于Django的权限系统扩展:
# 自定义权限装饰器 def role_required(*roles): def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): if request.user.profile.role not in roles: raise PermissionDenied return view_func(request, *args, **kwargs) return _wrapped_view return decorator # 使用示例 @role_required('counselor', 'admin') def view_student_report(request, student_id): ...5. 部署优化实践
5.1 性能调优方案
实测中发现的两个性能瓶颈及解决方案:
测评提交并发问题:
- 现象:高峰期出现答题记录丢失
- 解决:引入Celery异步任务队列
@app.task(bind=True) def save_answer_task(self, user_id, question_id, score): try: AnswerRecord.objects.create( user_id=user_id, question_id=question_id, score=score ) except IntegrityError: self.retry(countdown=60)分析报表生成慢:
- 优化:预计算+缓存策略
- 使用Django的cache框架:
from django.core.cache import cache def get_student_report(user_id): cache_key = f"report_{user_id}" report = cache.get(cache_key) if not report: report = generate_report(user_id) # 耗时操作 cache.set(cache_key, report, timeout=3600) return report
5.2 监控体系建设
使用Prometheus + Grafana搭建监控看板,关键指标包括:
- 测评完成率
- 各维度平均分变化趋势
- API响应时间P99值
- 异常答题模式检测(如所有题目选同一选项)
配置示例:
# prometheus.yml 片段 scrape_configs: - job_name: 'django' metrics_path: '/metrics' static_configs: - targets: ['web:8000'] - job_name: 'celery' static_configs: - targets: ['celery:8888']6. 典型问题排查实录
6.1 跨框架会话共享问题
症状:Django和Flask之间登录状态丢失 根本原因:两个框架默认使用不同的session加密密钥 解决方案:
# settings.py DJANGO_SECRET_KEY = 'your_django_secret' # flask_app.py app.secret_key = DJANGO_SECRET_KEY # 使用相同密钥 # 同时配置共享的session存储后端 SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"6.2 数据分析内存溢出
现象:生成年级报告时服务器崩溃 排查过程:
- 发现是Pandas加载全部作答记录导致
- 改用Django的iterator()方法流式处理
def batch_analyze(queryset, batch_size=1000): for i in range(0, queryset.count(), batch_size): batch = queryset[i:i+batch_size] df = pd.DataFrame.from_records(batch.values()) yield process_batch(df)7. 项目演进方向
在实际运行半年后,总结出三个优化方向:
移动端适配:
- 开发微信小程序版本
- 利用Flask的REST API复用后端逻辑
- 添加离线答题功能
智能分析增强:
- 引入LSTM模型预测心理状态变化趋势
- 使用TF-IDF分析开放题文本情绪
多租户支持:
- 抽象出院校配置模块
- 实现测评量表和报表模板的自定义
- 基于Django的sites框架改造
这个项目给我的最大启示是:技术选型需要服务于业务场景。Django和Flask的混用看似非常规,但在需要兼顾管理后台复杂性和前端灵活性的场景下,反而产生了1+1>2的效果。后续计划将核心模块抽象为Python包,方便其他高校快速部署。