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 %}
    

创建课程

{% csrf_token %} {{form.as_p}}
{% 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 }}

{% csrf_token %} {{form.as_p}}
{% 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 %}
    
{% csrf_token %}
{% for course in course_list %} {% endfor %}
课程编号 名称 学分 当前人数
/总人数
年份 学期 状态 操作
{{ 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 %}
{% 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 %} {% endfor %}
编号 详情 操作
{{ schedule.id }} {{ schedule }}

学生列表 {% if course.status == 4 %} {% endif %}

{% for cs in course_students %} {% endfor %}
学生学号 学生姓名 学生邮箱 得分 评价 操作
{{ 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 %}
{% if course.status == 5 %}

学生评价

{% for cs in sorted_course_students %} {% if cs.rating != None %} {% endif %} {% endfor %}
学生评分 学生评价
{{ cs.rating }} {{ cs.assessment }}
{% 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 }}

{% csrf_token %} {{form.as_p}}
{% 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 效果

创建课程页面:

教师主页:

教师课程详情页:

添加课程时刻表页面:

相关