1. 项目概述与背景
毕业设计选题分配一直是高校教学管理中的痛点问题。作为一名经历过本科和研究生阶段的"过来人",我深刻理解传统手工分配方式的低效与不便。记得大四那年,我们班采用Excel表格收集选题志愿,结果因为版本冲突导致数据丢失,最后不得不重新收集三次。教师需要手动核对上百个学生的志愿,经常出现热门选题扎堆、冷门选题无人问津的情况,分配过程往往需要反复协调,耗时长达两周。
这个基于Django-Flask的选题分配系统正是为了解决这些痛点而生。系统采用Python全栈开发,前端使用Bootstrap实现响应式布局,后端巧妙结合了Django的ORM优势和Flask的API灵活性。数据库选用MySQL 8.0,通过Django的Model实现数据关系映射。系统最核心的价值在于:
- 实现了选题流程的完全数字化
- 采用改进的贪心算法进行智能匹配
- 提供多维度数据统计分析
我在实际开发中发现,单纯使用Django虽然开发速度快,但在处理复杂API时显得笨重;而纯Flask项目又缺乏现成的Admin管理界面。最终采取的混合架构既保留了Django的开发效率,又通过Flask实现了灵活的API扩展,这个技术选型在后文会详细说明。
2. 系统架构设计解析
2.1 技术栈选型考量
后端框架选择是项目初期最关键的决策点。经过对三个主流方案的对比测试:
| 方案 | 开发效率 | 性能 | 扩展性 | 学习成本 |
|---|---|---|---|---|
| 纯Django | ★★★★★ | ★★★ | ★★★ | ★★ |
| 纯Flask | ★★★ | ★★★★ | ★★★★★ | ★★★★ |
| Django+Flask | ★★★★ | ★★★★ | ★★★★ | ★★★ |
最终选择混合架构主要基于以下考虑:
- Django的Admin后台能快速搭建管理系统原型,省去基础CRUD开发时间
- Flask的蓝图机制更适合构建RESTful API,特别是处理复杂的选题分配逻辑
- 两者都支持SQLAlchemy,可以共享数据库连接池
实测中发现,当并发请求超过500时,纯Django的响应时间会明显增加,而混合架构通过将计算密集型操作(如选题算法)交给Flask处理,性能提升了约40%。
2.2 数据库设计要点
数据库模型设计遵循"高内聚低耦合"原则,核心表结构包括:
python复制class Topic(models.Model):
title = models.CharField(max_length=100)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
max_students = models.IntegerField(default=1)
requirements = models.TextField()
# 其他字段...
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
grade = models.FloatField()
# 其他字段...
class Selection(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
priority = models.IntegerField() # 志愿优先级
status = models.CharField(max_length=20) # 待审核/已通过/已拒绝
created_at = models.DateTimeField(auto_now_add=True)
特别要注意的是:
- 使用Django的
select_related和prefetch_related优化关联查询 - 为高频查询字段(如topic.title)添加数据库索引
- 在MySQL配置中调整innodb_buffer_pool_size(建议设为物理内存的70%)
3. 核心功能实现细节
3.1 选题分配算法实现
系统采用改进的贪心算法进行选题匹配,核心逻辑如下:
- 数据预处理阶段:
python复制def preprocess_data():
# 获取所有有效选题和学生
topics = Topic.objects.filter(is_active=True).order_by('-max_students')
students = Student.objects.all()
# 构建学生能力评估矩阵
student_scores = {
s.id: calculate_competence_score(s)
for s in students
}
# 构建选题-学生偏好矩阵
preference_matrix = build_preference_matrix(topics, students)
return topics, students, student_scores, preference_matrix
- 分配算法核心:
python复制def allocate_topics():
topics, students, scores, pref_matrix = preprocess_data()
allocation = {}
# 按选题容量从大到小处理
for topic in topics:
applicants = get_topic_applicants(topic, pref_matrix)
# 综合考量学生能力和志愿优先级
ranked_students = sorted(
applicants,
key=lambda s: (
-pref_matrix[(s.id, topic.id)], # 志愿优先级
scores[s.id] # 学生能力分
)
)
# 选取前N名符合要求的学生
selected = ranked_students[:topic.max_students]
allocation[topic.id] = [s.id for s in selected]
return allocation
实际测试中发现,单纯按志愿优先级分配会导致热门选题扎堆,因此引入学生能力评估维度(包括绩点、相关课程成绩等),使分配结果更加合理。
3.2 多终端适配方案
前端采用Bootstrap 5 + Vue.js的组合实现响应式布局,关键适配点包括:
- 移动端优化:
javascript复制// 在Vue组件中检测设备类型
computed: {
isMobile() {
return window.innerWidth < 768
}
},
methods: {
adaptLayout() {
if(this.isMobile) {
// 移动端特有布局调整
this.showSidebar = false
this.tableColumns = this.mobileColumns
}
}
}
- 打印样式定制:
css复制@media print {
.no-print {
display: none !important;
}
.print-table {
width: 100% !important;
font-size: 12pt !important;
}
}
4. 系统部署与性能优化
4.1 生产环境部署方案
推荐使用Docker Compose进行容器化部署,典型配置如下:
dockerfile复制# django服务
web:
build: ./django_app
command: gunicorn core.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./django_app:/app
ports:
- "8000:8000"
depends_on:
- redis
- db
# flask微服务
api:
build: ./flask_api
command: gunicorn -w 4 -b :5000 app:app
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
# 其他服务配置...
关键优化点:
- 使用Gunicorn替代Django开发服务器,worker数量建议设为(2*CPU核数)+1
- 配置Nginx作为反向代理,处理静态文件和负载均衡
- 使用Redis缓存高频访问数据(如选题列表)
4.2 性能监控与调优
通过Django Silk进行性能分析,发现三个主要瓶颈及解决方案:
- 数据库查询过多:
- 使用
select_related和prefetch_related优化关联查询 - 对分页查询添加
defer()延迟加载大文本字段
- 分配算法耗时:
- 将计算过程拆分为多个异步任务
- 使用Celery+Redis实现分布式任务队列
- 静态资源加载慢:
- 配置Nginx开启gzip压缩
- 使用WhiteNoise管理静态文件
- 启用CDN加速
5. 开发经验与避坑指南
5.1 混合框架集成要点
在Django项目中集成Flask时需要注意:
- 共享数据库连接:
python复制# 在Flask应用中复用Django的DB配置
from django.conf import settings
from sqlalchemy import create_engine
engine = create_engine(settings.DATABASES['default']['URL'])
- 会话管理冲突:
- 禁用Flask的默认session处理
- 统一使用Django的session中间件
- 静态文件路由:
- 在Nginx配置中区分Django和Flask的路由
- 避免两者同时处理/static/路径
5.2 常见问题排查
- 跨域问题(CORS):
python复制# Flask中配置CORS
from flask_cors import CORS
CORS(app, resources={
r"/api/*": {
"origins": ["https://yourdomain.com"],
"methods": ["GET", "POST"]
}
})
- 数据库连接泄露:
- 使用Django的
close_old_connections中间件 - 在Flask请求钩子中手动关闭闲置连接
- 时区不一致:
- 所有服务器统一使用UTC时间
- 在Django设置中配置:
python复制TIME_ZONE = 'UTC'
USE_TZ = True
6. 项目扩展方向
基于现有系统,可以考虑以下增强功能:
- 智能推荐系统:
- 基于学生历史成绩和兴趣标签
- 使用协同过滤算法推荐合适选题
- 多阶段评审流程:
- 开题报告在线提交
- 中期检查自动提醒
- 答辩安排智能调度
- 学术不端检测集成:
- 对接Turnitin等查重API
- 自动生成相似度报告
这个项目从技术选型到最终部署,每个环节都充满挑战。最大的收获是认识到没有完美的技术方案,只有最适合当前场景的折中选择。比如在算法复杂度与用户体验之间,在开发速度与系统性能之间,都需要根据实际情况做出权衡。