作为一名有多年Django开发经验的工程师,我最近完成了一个基于Django框架的学籍管理系统开发项目。这个系统是为高校设计的综合性管理平台,旨在解决传统学籍管理中存在的效率低下、数据孤岛等问题。系统采用B/S架构,前端使用Vue.js,后端采用Django+MySQL技术栈,实现了学生信息管理、课程管理、活动管理、奖惩记录等核心功能模块。
在实际开发过程中,我发现很多学校的学籍管理仍停留在Excel表格和纸质档案阶段,不仅查询效率低,而且容易出现数据不一致的情况。这个系统通过信息化手段,将学生从入学到毕业的全生命周期管理数字化,大大提升了教务管理的工作效率。系统上线后,某高校的学籍查询时间从原来的平均15分钟缩短到3秒内,选课系统的并发处理能力达到每秒2000次请求。
选择Django作为后端框架主要基于以下几个考虑:
前端选择Vue.js是因为:
数据库选择MySQL 8.0主要考虑:
系统采用典型的三层架构:
code复制表示层(Vue.js) ←→ 业务逻辑层(Django) ←→ 数据层(MySQL)
关键设计要点:
提示:在设计API时,我遵循了Richardson成熟度模型Level 3的标准,为每个资源设计HATEOAS风格的接口,使前端可以动态发现可用操作。
学生信息是系统的核心数据,我们设计了以下数据结构:
python复制class Student(models.Model):
student_id = models.CharField(max_length=20, unique=True) # 学号
name = models.CharField(max_length=50) # 姓名
gender = models.CharField(max_length=10, choices=GENDER_CHOICES)
birth_date = models.DateField()
id_card = models.CharField(max_length=18) # 身份证号
college = models.ForeignKey(College, on_delete=models.PROTECT)
major = models.ForeignKey(Major, on_delete=models.PROTECT)
class_name = models.CharField(max_length=50) # 班级
enrollment_date = models.DateField() # 入学日期
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='normal'
) # 学籍状态
class Meta:
indexes = [
models.Index(fields=['student_id']),
models.Index(fields=['name']),
models.Index(fields=['college', 'major']),
]
实现要点:
课程管理包含课程信息维护、选课退课等功能。核心模型设计:
python复制class Course(models.Model):
code = models.CharField(max_length=20, unique=True) # 课程代码
name = models.CharField(max_length=100)
credit = models.DecimalField(max_digits=3, decimal_places=1) # 学分
hours = models.PositiveSmallIntegerField() # 学时
teacher = models.ForeignKey(Teacher, on_delete=models.PROTECT)
capacity = models.PositiveSmallIntegerField() # 容量
current = models.PositiveSmallIntegerField(default=0) # 当前人数
schedule = JSONField() # 上课时间安排
def is_available(self):
return self.current < self.capacity
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
enroll_time = models.DateTimeField(auto_now_add=True)
score = models.DecimalField(
max_digits=4,
decimal_places=1,
null=True,
blank=True
)
class Meta:
unique_together = [['student', 'course']]
选课业务逻辑实现:
python复制def enroll_course(student_id, course_id):
try:
with transaction.atomic():
student = Student.objects.select_for_update().get(pk=student_id)
course = Course.objects.select_for_update().get(pk=course_id)
if not course.is_available():
raise ValueError("课程已满")
if Enrollment.objects.filter(student=student, course=course).exists():
raise ValueError("不能重复选课")
Enrollment.objects.create(student=student, course=course)
course.current += 1
course.save()
return True
except Exception as e:
logger.error(f"选课失败: {str(e)}")
raise
系统采用RBAC权限模型,主要角色包括:
权限控制实现:
python复制# permissions.py
from rest_framework import permissions
class IsAdmin(permissions.BasePermission):
def has_permission(self, request, view):
return request.user.is_authenticated and request.user.role == 'admin'
class IsTeacher(permissions.BasePermission):
def has_permission(self, request, view):
return request.user.is_authenticated and request.user.role == 'teacher'
# views.py
class StudentViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdmin]
queryset = Student.objects.all()
serializer_class = StudentSerializer
class CourseViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Course.objects.all()
serializer_class = CourseSerializer
def get_permissions(self):
if self.action in ['create', 'update', 'destroy']:
return [IsTeacher()]
return super().get_permissions()
python复制# 不好的写法:会产生N+1查询问题
students = Student.objects.all()
for s in students:
print(s.college.name)
# 优化后的写法
students = Student.objects.select_related('college').all()
python复制from django.db.models import Count, Avg
courses = Course.objects.annotate(
student_count=Count('enrollment'),
avg_score=Avg('enrollment__score')
).filter(student_count__gt=0)
python复制# 只获取需要的字段,减少数据传输量
student_names = Student.objects.values_list('name', flat=True)
python复制from django.core.cache import cache
def get_student_count():
key = 'student_count'
count = cache.get(key)
if count is None:
count = Student.objects.count()
cache.set(key, count, timeout=60*60) # 缓存1小时
return count
python复制from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 缓存15分钟
def student_list(request):
...
对于耗时的操作如生成报表、发送通知等,使用Celery异步处理:
python复制# tasks.py
from celery import shared_task
@shared_task
def generate_report(report_type):
# 生成报表的逻辑
pass
# views.py
def create_report(request):
generate_report.delay('student_stats')
return Response({"status": "started"})
我们使用Docker Compose部署整个系统,docker-compose.yml关键配置:
yaml复制version: '3'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6
ports:
- "6379:6379"
web:
build: .
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
- redis
celery:
build: .
command: celery -A config worker -l info
volumes:
- .:/code
depends_on:
- db
- redis
volumes:
mysql_data:
python复制LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/var/log/django/debug.log',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
}
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
python复制# settings.py
INSTALLED_APPS = [
...
'debug_toolbar',
]
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
...
]
INTERNAL_IPS = ['127.0.0.1']
python复制from django.db.models import F
Course.objects.filter(pk=course_id).update(current=F('current') + 1)
python复制from django.db import transaction
def do_something():
with transaction.atomic():
# 数据库操作
transaction.on_commit(lambda: send_notification())
python复制from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Student)
def clear_student_cache(sender, instance, **kwargs):
cache.delete('student_count')
这个项目让我深刻体会到Django在快速开发企业级应用方面的优势。通过合理的设计和优化,即使是相对复杂的学籍管理系统也能保持较高的开发效率和系统性能。