zoukankan      html  css  js  c++  java
  • 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 %}
        <h3>创建课程</h3>
        <div class="form create-update-from">
            <form method="post">
                {% csrf_token %}
                {{form.as_p}}
                <div class="submit-button">
                    <input type="submit" value="创建"/>
                    <input type="button" value="返回"  onclick='window.open("{% url 'course' "teacher"%}")' />
                </div>
            </form>
        </div>
    {% 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 %}
        <h3>创建时刻表:&nbsp;&nbsp;&nbsp;&nbsp;[{{ course.id }}] {{ course.name }}</h3>
        <div class="form create-update-from">
            <form method="post">
                {% csrf_token %}
                {{form.as_p}}
                <div class="submit-button">
                    <input type="submit" value="创建"/>
                    <input type="button" value="返回"  onclick='window.open("{% url 'view_detail' course.id%}")' />
                </div>
            </form>
        </div>
    {% 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 %}
        <div class="main-container">
            <div class="main-bar">
                <form class="search-form" method="post">
                    {% csrf_token %}
                    <input class="input" id="search-key" type="text" name="search" {% if search_key != None %}value="{{ search_key }}" {% endif %}/>
                    <input class="button" type="submit" value="搜索课程" />
                </form>
    
                <input class="button right-button" type="button" value="创建课程"  onclick='window.open("{% url 'create_course' %}")' />
            </div>
            <table class="item-list course-list">
                <thead>
                    <tr>
                        <th class="course-no">课程编号</th>
                        <th class="course-name">名称</th>
                        <th class="course-credit">学分</th>
                        <th class="course-number">当前人数<br>/总人数</th>
                        <th class="course-year">年份</th>
                        <th class="course-semester">学期</th>
                        <th class="course-status">状态</th>
                        <th class="course-operation">操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for course in course_list %}
                        <tr id="course-id-{{ course.id }}">
                        <td class="course-no">{{ course.id }}</td>
                        <td class="course-name">{{ course.name }}</td>
                        <td class="course-credit">{{ course.credit }}</td>
                        <td class="course-number">{{ course.get_current_count }}/{{ course.max_number }}</td>
                        <td class="course-year">{{ course.year }}</td>
                        <td class="course-semester">{{ course.get_semester_display }}</td>
                        <td class="course-status">{{ course.get_status_text }}</td>
                        <td class="course-operation">
                            {% if course.status < 4 %}
                                <input class="button right-button" type="button" value="{{ course.get_op_text }}"
                                  onclick='location.href="{% url 'handle_course' course.id course.status %}"' />
                            {% endif %}
                            {% if course.status == 4 %}
                            {# 结课后给分 #}
                                <input class="button right-button" type="button" value="{{ course.get_op_text }}"
                                       onclick='location.href="{% url 'view_detail' course.id %}"' />
                            {% else %}
                                <input class="button right-button" type="button" value="查看详情"
                                       onclick='location.href="{% url 'view_detail' course.id %}"' />
                            {% endif %}
                        </td>
                        </tr>
                    {% endfor %}
                </tbody>
    
            </table>
        </div>
    {% 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 %}
        <h3>课程详情<input class="button right-button" type="button" value="返回主页"
                       onclick='window.open("{% url 'course' 'teacher'%}")'/></h3>
        <table class="item-list detail-list">
            <thead>
                <tr>
                    <th>课程编号</th>
                    <th>名称</th>
                    <th>学分</th>
                    <th>当前人数/总人数</th>
                    <th>年份</th>
                    <th>学期</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>{{ course.id }}</td>
                    <td>{{ course.name }}</td>
                    <td>{{ course.credit }}</td>
                    <td>{{ course.get_current_count }}/{{ course.max_number }}</td>
                    <td>{{ course.year }}</td>
                    <td>{{ course.get_semester_display }}</td>
                </tr>
            </tbody>
        </table>
    
        <h3>上课时间<input class="button right-button" type="button" value="添加时间表" onclick='window.open("{% url 'create_schedule' course.id%}")'/></h3>
        <table class="item-list schedule-list">
            <thead>
                <tr>
                    <th class="schedule-no">编号</th>
                    <th class="schedule-no">详情</th>
                    <th class="schedule-no">操作</th>
                </tr>
            </thead>
            <tbody>
                {% for schedule in schedules %}
                <tr>
                    <td>{{ schedule.id }}</td>
                    <td>{{ schedule }}</td>
                    <td>
                        <input class="button" type="button" value="删除"
                               onclick='window.open("{% url 'delete_schedule' schedule.id%}?course_id={{ course.id }}")'/>
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    
        <h3>学生列表
            {% if course.status == 4 %}
                <input class="button right-button" type="button" value="给分完成" onclick='location.href="{% url 'handle_course' course.id 4%}"' />
            {% endif %}
        </h3>
        <table class="item-list student-list">
            <thead>
                <tr>
                    <th class="student-no">学生学号</th>
                    <th class="student-name">学生姓名</th>
                    <th class="student-email">学生邮箱</th>
                    <th class="student-score">得分</th>
                    <th class="student-comments">评价</th>
                    <th class="operation">操作</th>
                </tr>
            </thead>
            <tbody>
                {% for cs in course_students %}
                <tr>
                    <td>{{ cs.student.get_id}}</td>
                    <td>{{ cs.student.name }}</td>
                    <td>{{ cs.student.email }}</td>
                    <td>
                        {% if cs.scores == None %}-{% endif %}
                        {% if cs.scores != None %}{{ cs.scores }}{% endif %}
                    </td>
                    <td>
                        {% if cs.scores == None %}-{% endif %}
                        {% if cs.scores != None %}{{ cs.comments }}{% endif %}
                    </td>
                    <td class="operation">
                        {% if course.status == 4 %}
                            {% if cs.scores == None %}
                                <input class="button right-button" type="button" value="给分"
                                   onclick='location.href="{% url 'score' cs.id%}"' />
                            {% else %}
                                <input class="button right-button" type="button" value="修改成绩"
                                   onclick='location.href="{% url 'score' cs.id%}?update=1"' />
                            {% endif %}
                        {% else %}
                            -
                        {% endif %}
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    
        {% if course.status == 5 %}
        <h3>学生评价</h3>
        <table class="item-list student-list">
            <thead>
                <tr>
                    <th class="student-score">学生评分</th>
                    <th class="student-comments">学生评价</th>
                </tr>
            </thead>
            <tbody>
                {% for cs in sorted_course_students %}
                {% if cs.rating != None %}
                <tr>
                    <td>{{ cs.rating }}</td>
                    <td>{{ cs.assessment }}</td>
                </tr>
                {% endif %}
                {% endfor %}
            </tbody>
        </table>
        {% 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 += "<div>%s 未打分</div>" % 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 %}
        <h3>{{ title }}</h3>
        <div class="form create-update-from">
            <form method="post">
                {% csrf_token %}
                {{form.as_p}}
                <div class="submit-button">
                    <input type="submit" value="确定"/>
                    <input type="button" value="返回"  onclick='location.href="{{ return_url }}"' />
                </div>
            </form>
        </div>
    {% endblock %}
    

    5 添加url

    上面已经把老师需要的视图方法全部实现完毕了,接下来就是添加到路由里面。
    修改后的course/urls.py如下

    from django.urls import path
    from course.views import *
    from course.cbvs import ScoreUpdateView
    
    
    urlpatterns = [
        path('<slug:kind>/', home, name="course"),
        path('<slug:kind>/', home, name="course"),
        path('teacher/create_course', create_course, name="create_course"),
        path('teacher/view_detail/<int:course_id>', view_detail, name="view_detail"),
        path('teacher/create_schedule/<int:course_id>', create_schedule, name="create_schedule"),
        path('teacher/delete_schedule/<int:schedule_id>', delete_schedule, name="delete_schedule"),
        path('teacher/score/<int:pk>', ScoreUpdateView.as_view(), name="score"),
        path('teacher/handle_course/<int:course_id>/<int:handle_kind>', handle_course, name="handle_course"),
    ]
    

    6 效果

    创建课程页面:

    教师主页:

    教师课程详情页:

    添加课程时刻表页面:

  • 相关阅读:
    css--display详解
    关于overflow:hidden的作用
    float 应用
    flex 布局
    CSS+DIV布局中absolute和relative的区别
    线程和进程的区别是什么?
    .NET中读写SQL Server数据库需要用到哪些类?作用是什么?
    C# CookieHelper
    git pull/push代码 每次都要输入账户名和密码的解决方法
    git拉取远程分支到本地
  • 原文地址:https://www.cnblogs.com/BigShuang/p/14324487.html
Copyright © 2011-2022 走看看