Django 小实例S1 简易学生选课管理系统 10 老师课程业务实现
Django 小实例S1 简易学生选课管理系统 第10节——老师课程业务实现
作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师。
课程模块中,老师将要使用到的功能有:
- 创建课程
- 添加、删除课程时刻表
- 查看课程列表
- 操作课程:修改状态,给学生打分
这里一个一个实现
首先,在course/views.py
中将课程的模型类全部导入,以便后面使用
from .models import Course, Schedule, StudentCourse
1 - 创建课程
首先需要实现的是创建课程的表单,
新建course/forms.py
如下
from django import forms
from .models import Course, Schedule, StudentCourse
class CourseForm(forms.ModelForm):
class Meta:
model = Course
exclude = ['status', 'teacher']
同时对于新建课程的请求,在constants.py
中添加一个非法请求的响应如下
INVALID_REQUEST_METHOD = "Invalid request method."
新建对应模板templates/course/teacher/create_course.html
如下
{% extends "course/nav.html" %}
{% block title %}创建课程{% endblock %}
{% block content %}
创建课程
{% endblock %}
再在course/views.py
中导入CourseForm
类和INVALID_REQUEST_METHOD
常量,然后添加代码如下
def create_course(request):
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
info = {
"name": user.name,
"kind": "teacher",
}
if request.method == 'POST':
form = CourseForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.status = 1
obj.teacher = user
obj.save()
return redirect(reverse("course", kwargs={"kind": "teacher"}))
elif request.method == 'GET':
form = CourseForm()
else:
return HttpResponse(INVALID_REQUEST_METHOD)
return render(request, 'course/teacher/create_course.html', {'info': info, 'form': form})
2 - 添加、删除课程时刻表
先需要实现的是添加课程时刻表的表单,
在course/forms.py
中添加代码如下
class ScheduleForm(forms.ModelForm):
class Meta:
model = Schedule
exclude = ["course"]
新建对应模板templates/course/teacher/create_schedule.html
如下
{% extends "course/nav.html" %}
{% block title %}创建时刻表{% endblock %}
{% block content %}
创建时刻表: [{{ course.id }}] {{ course.name }}
{% endblock %}
在course/views.py
中导入这个表单,
然后添加代码如下
def create_schedule(request, course_id):
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
info = {
"name": user.name,
"kind": "teacher",
}
course = Course.objects.get(pk=course_id)
if request.method == 'POST':
form = ScheduleForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.course = course
obj.save()
return redirect(reverse("view_detail", kwargs={"course_id": course_id}))
elif request.method == 'GET':
form = ScheduleForm()
else:
return HttpResponse(INVALID_REQUEST_METHOD)
return render(request, 'course/teacher/create_schedule.html', {'info': info, 'form': form, "course": course})
def delete_schedule(request, schedule_id):
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
schedule = Schedule.objects.get(pk=schedule_id)
course_id = request.GET.get("course_id") or schedule.course.id
schedule.delete()
return redirect(reverse("view_detail", kwargs={"course_id": course_id}))
3 查看课程列表
在本项目中,老师和学生的个人主页就是其课程主页,将展示其所有课程列表。
为老师的课程主页添加模板templates/course/teacher/home.html
如下
{% extends "course/nav.html" %}
{% block title %}HomePage{% endblock %}
{% block content %}
课程编号
名称
学分
当前人数
/总人数
年份
学期
状态
操作
{% for course in course_list %}
{{ course.id }}
{{ course.name }}
{{ course.credit }}
{{ course.get_current_count }}/{{ course.max_number }}
{{ course.year }}
{{ course.get_semester_display }}
{{ course.get_status_text }}
{% if course.status < 4 %}
{% endif %}
{% if course.status == 4 %}
{# 结课后给分 #}
{% else %}
{% endif %}
{% endfor %}
{% endblock %}
查看课程列表要写在老师的主页视图中
即修改course/views.py
中的teacher_home
如下
def teacher_home(request):
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
info = {
"name": user.name,
"kind": "teacher",
}
is_search = False
search_key = ""
if request.method == "POST":
search_key = request.POST.get("search")
if search_key:
is_search = True
context = {"info": info}
q = Q(teacher=user)
if is_search:
q = q & Q(name__icontains=search_key)
context["search_key"] = search_key
context["course_list"] = Course.objects.filter(q).order_by('status')
return render(request, 'course/teacher/home.html', context)
里面使用了django.db.models.Q
类,所以要在开头添加代码from django.db.models import Q
导入这个类
补充说明:这里面还实现了一个搜索框,能够根据关键词去搜索课程。
为了不使用js,搜索框的信息是通过post表单信息来提交的。
4 操作课程
老师在课程主页,可以进行常规的课程状态修改:
开始选课,结束选课,结课。
而打分则需要在课程详情页去给。
所以这里一方面要实现一个课程主页的操作视图,
也要实现一个课程详情页视图,打分在本文第五部分去做。
先添加一个课程详情页的模板文件templates/course/teacher/course.html
如下:
{% extends "course/nav.html" %}
{% block title %}课程详情{% endblock %}
{% block content %}
课程详情
课程编号
名称
学分
当前人数/总人数
年份
学期
{{ course.id }}
{{ course.name }}
{{ course.credit }}
{{ course.get_current_count }}/{{ course.max_number }}
{{ course.year }}
{{ course.get_semester_display }}
上课时间
编号
详情
操作
{% for schedule in schedules %}
{{ schedule.id }}
{{ schedule }}
{% endfor %}
学生列表
{% if course.status == 4 %}
{% endif %}
学生学号
学生姓名
学生邮箱
得分
评价
操作
{% for cs in course_students %}
{{ cs.student.get_id}}
{{ cs.student.name }}
{{ cs.student.email }}
{% if cs.scores == None %}-{% endif %}
{% if cs.scores != None %}{{ cs.scores }}{% endif %}
{% if cs.scores == None %}-{% endif %}
{% if cs.scores != None %}{{ cs.comments }}{% endif %}
{% if course.status == 4 %}
{% if cs.scores == None %}
{% else %}
{% endif %}
{% else %}
-
{% endif %}
{% endfor %}
{% if course.status == 5 %}
学生评价
学生评分
学生评价
{% for cs in sorted_course_students %}
{% if cs.rating != None %}
{{ cs.rating }}
{{ cs.assessment }}
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
在course/views.py
中添加代码如下
def handle_course(request, course_id, handle_kind):
"""
:param request:
:param course_id:
:param handle_kind:
1: "开始选课",
2: "结束选课",
3: "结课",
4: "给分完成"
:return:
"""
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
info = {
"name": user.name,
"kind": "teacher",
}
course = Course.objects.get(pk=course_id)
if course.status == handle_kind and course.status < 5:
if course.status == 4:
scs = StudentCourse.objects.filter(course=course)
all_given = True
res = ""
for sc in scs:
if sc.scores is None:
all_given = False
res += "%s 未打分" % sc.student
if all_given:
course.status += 1
course.save()
return redirect(reverse("view_detail", kwargs={"course_id": course.id}))
else:
return HttpResponse(res)
else:
course.status += 1
course.save()
course_list = Course.objects.filter(teacher=user)
return render(request, 'course/teacher/home.html', {'info': info, 'course_list': course_list})
def view_detail(request, course_id):
user = get_user(request, "teacher")
if not user:
return redirect(reverse("login", kwargs={"kind": "teacher"}))
info = {
"name": user.name,
"kind": "teacher",
}
course = Course.objects.get(pk=course_id)
c_stu_list = StudentCourse.objects.filter(course=course)
sche_list = Schedule.objects.filter(course=course)
context = {
"info": info,
"course": course,
"course_students": c_stu_list,
"schedules": sche_list
}
if course.status == 5:
sorted_cs_list = sorted(c_stu_list, key=lambda cs: cs.scores)
context["sorted_course_students"] = sorted_cs_list
return render(request, "course/teacher/course.html", context)
5 打分
学生的分数是记录在学生课程关系表中的,
在学生选课成功后会新建一条对应的数据。
给分,则是修改其中的分数字段,即对学生课程表模型进行更新。
这里我们首选CBVs中的UpdateView
,
不过要先给这个视图建立一个表单,在course/forms.py
中添加代码如下
class ScoreForm(forms.ModelForm):
class Meta:
model = StudentCourse
fields = ["student", "course", "scores", "comments"]
student = forms.CharField(label="学生", disabled=True)
# course = forms.CharField(widget=forms.TextInput(attrs={'readonly': 'readonly'}))
course = forms.CharField(label="课程", disabled=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.initial['student'] = self.instance.student
self.initial['course'] = self.instance.course
def clean_student(self):
return self.initial['student']
def clean_course(self):
return self.initial['course']
新建course/cbvs.py
如下:
from django.views.generic.edit import DeleteView, CreateView, UpdateView
from django.views.generic.detail import DetailView
from django.shortcuts import render, reverse, redirect
# Relative import of GeeksModel
from .models import Schedule, StudentCourse
from .forms import ScoreForm
class ScoreUpdateView(UpdateView):
model = StudentCourse
form_class = ScoreForm
template_name = 'course/teacher/score.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
title = "给分"
if request.GET.get("update"):
title = "修改成绩"
info = {}
return_url = reverse("course", kwargs={"kind": "teacher"})
if self.object:
teacher = self.object.course.teacher
info = {
"name": teacher.name,
"kind": "teacher",
}
return_url = reverse("view_detail", kwargs={"course_id": self.object.course.id})
return self.render_to_response(self.get_context_data(info=info, title=title, return_url=return_url))
def get_success_url(self):
if self.object:
return reverse("view_detail", kwargs={"course_id": self.object.course.id})
else:
return reverse("course", kwargs={"kind": "teacher"})
同时补上其对应的模板文件templates/course/teacher/score.html
如下
{% extends "course/nav.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
{{ title }}
{% endblock %}
5 添加url
上面已经把老师需要的视图方法全部实现完毕了,接下来就是添加到路由里面。
修改后的course/urls.py
如下
from django.urls import path
from course.views import *
from course.cbvs import ScoreUpdateView
urlpatterns = [
path('/', home, name="course"),
path('/', home, name="course"),
path('teacher/create_course', create_course, name="create_course"),
path('teacher/view_detail/', view_detail, name="view_detail"),
path('teacher/create_schedule/', create_schedule, name="create_schedule"),
path('teacher/delete_schedule/', delete_schedule, name="delete_schedule"),
path('teacher/score/', ScoreUpdateView.as_view(), name="score"),
path('teacher/handle_course//', handle_course, name="handle_course"),
]
6 效果
创建课程页面:
教师主页:
教师课程详情页:
添加课程时刻表页面: