这个基于Django的学生选课系统是我最近完成的一个毕业设计项目,也是我在高校教学管理系统领域的一次实践探索。作为一名有多年开发经验的程序员,我深知一个优秀的选课系统对于高校教务管理的重要性。传统的选课方式往往存在系统崩溃、选课不公平、数据统计困难等问题,而这个项目正是为了解决这些痛点而设计的。
系统采用了Django作为后端框架,配合MySQL数据库和Vue.js前端技术,实现了完整的选课流程管理、课程管理、学生管理等功能模块。整个系统从需求分析、架构设计到编码实现,再到最后的测试部署,都是我亲自操刀完成的。在这个过程中,我积累了不少实战经验,也踩过一些坑,今天就把这个项目的完整实现过程分享给大家。
在项目启动阶段,我花了大量时间进行技术选型的调研和比较。最终确定的技术栈如下:
后端框架:Django
数据库:MySQL 8.0
前端技术:Vue.js + Element UI
系统采用了经典的三层架构设计:

这种分层架构的优势在于:
系统的主要数据模型包括:
以下是几个核心表的设计:
用户表(users_user)
sql复制CREATE TABLE `users_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`password` varchar(128) NOT NULL,
`last_login` datetime(6) DEFAULT NULL,
`is_superuser` tinyint(1) NOT NULL,
`username` varchar(150) NOT NULL,
`first_name` varchar(150) NOT NULL,
`last_name` varchar(150) NOT NULL,
`email` varchar(254) NOT NULL,
`is_staff` tinyint(1) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`date_joined` datetime(6) NOT NULL,
`user_type` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
课程表(courses_course)
sql复制CREATE TABLE `courses_course` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(20) NOT NULL,
`name` varchar(100) NOT NULL,
`credit` int(11) NOT NULL,
`description` longtext,
`department` varchar(50) NOT NULL,
`created_at` datetime(6) NOT NULL,
`updated_at` datetime(6) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
选课记录表(selections_selection)
sql复制CREATE TABLE `selections_selection` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(20) NOT NULL,
`created_at` datetime(6) NOT NULL,
`updated_at` datetime(6) NOT NULL,
`class_id` int(11) NOT NULL,
`student_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `selections_selection_class_id_3a1a7b0a_fk_classes_class_id` (`class_id`),
KEY `selections_selection_student_id_5c8c3a0a_fk_users_user_id` (`student_id`),
CONSTRAINT `selections_selection_class_id_3a1a7b0a_fk_classes_class_id` FOREIGN KEY (`class_id`) REFERENCES `classes_class` (`id`),
CONSTRAINT `selections_selection_student_id_5c8c3a0a_fk_users_user_id` FOREIGN KEY (`student_id`) REFERENCES `users_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
为了提高系统性能,我采取了以下优化措施:
用户认证是系统的基础功能,我基于Django自带的认证系统进行了扩展:
python复制# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
USER_TYPE_CHOICES = (
('student', 'Student'),
('teacher', 'Teacher'),
('admin', 'Administrator'),
)
user_type = models.CharField(max_length=20, choices=USER_TYPE_CHOICES)
class Meta:
db_table = 'users_user'
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
student_id = models.CharField(max_length=20, unique=True)
department = models.CharField(max_length=50)
grade = models.CharField(max_length=10)
class Meta:
db_table = 'users_student'
认证流程:
选课是系统的核心功能,需要考虑并发控制和业务规则:
python复制# selections/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction
from django.utils import timezone
from .models import Selection
from classes.models import Class
from users.models import Student
class SelectionCreateAPIView(APIView):
def post(self, request):
student = request.user.student
class_id = request.data.get('class_id')
try:
class_obj = Class.objects.select_for_update().get(id=class_id)
except Class.DoesNotExist:
return Response({'error': 'Class not found'}, status=status.HTTP_404_NOT_FOUND)
# 检查选课时间是否在开放期间
if not (class_obj.selection_start <= timezone.now() <= class_obj.selection_end):
return Response({'error': 'Selection period is closed'}, status=status.HTTP_400_BAD_REQUEST)
# 检查课程容量
if class_obj.current_students >= class_obj.capacity:
return Response({'error': 'Class is full'}, status=status.HTTP_400_BAD_REQUEST)
# 检查是否已经选过该课程
if Selection.objects.filter(student=student, class_obj=class_obj).exists():
return Response({'error': 'Already selected this class'}, status=status.HTTP_400_BAD_REQUEST)
# 使用事务保证数据一致性
with transaction.atomic():
selection = Selection.objects.create(
student=student,
class_obj=class_obj,
status='selected'
)
class_obj.current_students += 1
class_obj.save()
return Response({'message': 'Selection successful'}, status=status.HTTP_201_CREATED)
选课业务规则:
课程管理功能主要面向教师和管理员:
python复制# courses/views.py
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from .models import Course
from .serializers import CourseSerializer
from .permissions import IsTeacherOrAdmin
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy']:
permission_classes = [IsAuthenticated, IsTeacherOrAdmin]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
权限控制:
为了保证系统质量,我采用了多种测试方法:
选课功能测试案例
| 测试场景 | 测试步骤 | 预期结果 | 实际结果 | 通过与否 |
|---|---|---|---|---|
| 正常选课 | 1. 学生登录 2. 选择开放选课的课程 3. 提交选课请求 |
选课成功,课程人数+1 | 符合预期 | ✔ |
| 选已满课程 | 1. 学生登录 2. 选择已满员的课程 3. 提交选课请求 |
返回"课程已满"错误 | 符合预期 | ✔ |
| 重复选课 | 1. 学生登录 2. 选择已选过的课程 3. 提交选课请求 |
返回"已选过该课程"错误 | 符合预期 | ✔ |
| 非选课时间 | 1. 学生登录 2. 选择未开放选课的课程 3. 提交选课请求 |
返回"不在选课时间内"错误 | 符合预期 | ✔ |
系统采用Docker容器化部署,主要组件包括:
部署架构图:
code复制客户端 → Nginx(负载均衡) → Gunicorn(Django应用)
↘ MySQL
↘ Redis
通过这个项目的实践,我获得了以下宝贵的经验:
基于我在这个项目中的经验,给正在开发类似系统的开发者几点建议:
这个Django学生选课系统项目从需求分析到最终部署,历时3个月完成。它不仅满足了我毕业设计的要求,更是一个可以实际应用的系统。通过这个项目,我不仅巩固了Django开发技能,还学到了很多系统设计和性能优化的实战经验。希望我的分享能给正在开发类似系统的同学一些启发和帮助。