在大学教务管理体系中,选课环节一直是师生互动的关键节点。传统纸质选课或简单电子表格登记的方式,往往面临课程容量不透明、选课冲突频发、数据统计滞后等问题。我去年为某高校开发的这套Python+Django选课系统,通过自动化排课算法和实时数据看板,将选课周期从原来的两周压缩到三天,冲突率下降82%。
这个系统特别适合两类开发者参考:
选择Django框架主要基于三个实际考量:
python复制# 典型的多对多模型设计示例
class Course(models.Model):
students = models.ManyToManyField('Student', through='Enrollment')
teachers = models.ForeignKey('Teacher', on_delete=models.CASCADE)
class Enrollment(models.Model):
student = models.ForeignKey('Student')
course = models.ForeignKey('Course')
select_time = models.DateTimeField(auto_now_add=True) # 精确记录选课时间戳
教务系统的核心难点在于处理高并发选课请求。我们在MySQL设计上做了这些优化:
重要提示:千万不可在Django的save()方法中直接计算余量,必须使用原子操作:
python复制with transaction.atomic(): course = Course.objects.select_for_update().get(pk=course_id) if course.remain > 0: course.remain -= 1 course.save()
系统需要处理三类冲突:
我们采用位图算法检测时间冲突:
python复制def check_schedule_conflict(new_course, selected_courses):
new_slots = {f"{day}{period}" for day,period in new_course.schedule}
for course in selected_courses:
if new_slots & {f"{day}{period}" for day,period in course.schedule}:
return True
return False
热门课程采用双队列机制:
当有余量释放时,系统会自动:
初期直接使用Django ORM保存时,出现课程余量为负的情况。解决方案:
sql复制ALTER TABLE courses ADD CONSTRAINT remain_nonnegative CHECK (remain >= 0);
为追踪选课热点,我们开发了ELK日志分析模块:
关键日志字段包括:
当需要支持万人级并发时,建议拆分为三个服务:
基于历史数据实现:
python复制def recommend_courses(student):
# 协同过滤算法
similar_students = Student.objects.filter(
major=student.major,
enrolled_courses__in=student.completed_courses()
).distinct()
return Course.objects.filter(
enrollment__student__in=similar_students
).exclude(
enrollment__student=student
).annotate(
count=Count('id')
).order_by('-count')[:5]
这套系统在实际部署时,有个容易被忽视的细节:选课开始前需要预热数据库连接池。我们吃过亏后发现,当8000名学生同时点击选课按钮时,没有预热的连接池会导致前30秒的请求全部超时。后来通过提前运行模拟请求脚本解决了这个问题。