zoukankan      html  css  js  c++  java
  • Django 小实例S1 简易学生选课管理系统 11 学生课程业务实现

    Django 小实例S1 简易学生选课管理系统 第11节——学生课程业务实现
    点击查看教程总目录
    作者自我介绍:b站小UP主时常直播编程+红警三python1对1辅导老师

    课程模块中,学生需要拥有的功能有:

    • 查看课程列表
    • 选课撤课
    • 结课后评教

    1 - 查看课程列表

    学生可以按类别view_kind查看课程,view_kind分为

    • current: 查看当前课程
    • is_end: 查看结课课程
    • select: 可选课的
    • withdraw: 可撤课的

    新建学生查看课程的模板templates/course/student/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>
    
                {% if view_kind != "select"%}
                    <input class="button right-button" type="button" value="选课"  onclick='window.open("{% url 'view_course' 'select' %}")' />
                {% endif %}
                {% if view_kind != "withdraw"%}
                    <input class="button right-button" type="button" value="撤课"  onclick='window.open("{% url 'view_course' 'withdraw' %}")' />
                {% endif %}
                {% if view_kind != "is_end"%}
                    <input class="button right-button" type="button" value="查看结课课程"  onclick='window.open("{% url 'view_course' 'is_end' %}")' />
                {% endif %}
                {% if view_kind != "current"%}
                    <input class="button right-button" type="button" value="查看当前课程"  onclick='window.open("{% url 'view_course' 'current' %}")' />
                {% endif %}
            </div>
            <h3>{% if view_kind == "select"%}
                    选课
                {% elif view_kind == "withdraw"%}
                    撤课
                {% elif  view_kind == "is_end"%}
                    查看结课课程
                {% elif view_kind == "current"%}
                    查看当前课程
                {% endif %}</h3>
            <table class="item-list course-list">
                <thead>
                    <tr>
                        <th class="course-no">课程编号</th>
                        <th class="course-name">名称</th>
                        <th class="course-credit">学分</th>
                        {% if view_kind == "is_end" %}
                            <th class="course-year-semester">年份学期</th>
                        {% else %}
                            <th class="course-number">当前人数/<br>最大人数</th>
                            <th class="course-year">年份</th>
                            <th class="course-semester">学期</th>
                        {% endif %}
                        <th class="course-teacher">教师</th>
                        {% if view_kind == "is_end" %}
                            <th class="course-scores">得分</th>
                            <th class="course-comments">评语</th>
                            <th class="course-rating">学生评分</th>
                            <th class="course-assessment">学生评价</th>
                            <th class="course-operation student-course">操作</th>
                        {% else %}
                            <th class="course-schedule">上课时间</th>
                            <th class="course-operation student-course">操作</th>
                        {% endif %}
                    </tr>
                </thead>
                <tbody>
                {% if view_kind == "is_end" %}
                    {# end course show student course #}
                    {% for sc in course_list %}
                    <tr id="course-id-{{ sc.course.id }}">
                        <td class="course-no">{{ sc.course.id }}</td>
                        <td class="course-name">{{ sc.course.name }}</td>
                        <td class="course-credit">{{ sc.course.credit }}</td>
                        <td class="course-year-semester">{{ sc.course.year }} {{ sc.course.get_semester_display }}</td>
                        <td class="course-teacher">{{ sc.course.teacher.name }}</td>
                        <td class="course-scores">{{ sc.scores }}</td>
                        <td class="course-comments">{{ sc.comments }}</td>
                        {% if sc.rating == None %}
                            <td class="course-rating">-</td>
                            <td class="course-assessment">-</td>
                            <td class="course-operation student-course">
                            <input class="button" type="button" value="查看详情" onclick='location.href="{% url 'sview_detail' sc.id%}"' />
                            <input class="button" type="button" value="评教"
                                   onclick='window.open("{% url 'evaluate' sc.id %}")' />
                            </td>
                        {% else %}
                            <td class="course-rating">{{ sc.rating }}</td>
                            <td class="course-assessment">{{ sc.assessment }}</td>
                            <td class="course-operation student-course">
                            <input class="button" type="button" value="查看详情" onclick='location.href="{% url 'sview_detail' sc.id%}"' />
                            </td>
                        {% endif %}
                    </tr>
                    {% endfor %}
                {% else %}
                    {% 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-teacher">{{ course.teacher.name }}</td>
                        <td class="course-schedule">
                            {% for schedule in course.get_schedules %}
                                <div>{{ schedule }}</div>
                            {% endfor %}
                        </td>
                            <td class="course-operation student-course">
                            {% if view_kind == "select"%}
                                <input class="button" type="button" value="选课"
                                       onclick='window.open("{% url 'operate_course' course.id 'select' %}")' />
                            {% endif %}
                            {% if view_kind == "withdraw"%}
                                <input class="button" type="button" value="撤课"
                                       onclick='window.open("{% url 'operate_course' course.id 'withdraw' %}")' />
                            {% endif %}
                            {% if view_kind == "current"%}
                                -
                            {% endif %}
                            </td>
                    </tr>
                    {% endfor %}
                {% endif %}
                </tbody>
    
            </table>
        </div>
    {% endblock %}
    

    然后在course/views.py中添加代码如下

    def view_course(request, view_kind):
        """
        :param view_kind:
            current: 查看当前课程
            is_end: 查看结课课程
            select: 选课
            withdraw: 撤课
        """
        user = get_user(request, "student")
        if not user:
            return redirect(reverse("login", kwargs={"kind": "student"}))
    
        is_search = False
        search_key = ""
        if request.method == "POST":
            search_key = request.POST.get("search")
            if search_key:
                is_search = True
    
        info = {
            "name": user.name,
            "kind": "student",
        }
    
        course_list = []
    
        if view_kind in ["select", "current", "withdraw", "is_end"]:
            if view_kind == "select":
                q = Q(status=2)
                if is_search:
                    q = q & (Q(name__icontains=search_key) | Q(teacher__name__icontains=search_key))
    
                course_list = Course.objects.filter(q)
    
                my_course = StudentCourse.objects.filter(Q(student=user) & Q(with_draw=False))
                my_cids = [c.course.id for c in my_course]
                course_list = [c for c in course_list if c.id not in my_cids]
            else:
                q = Q(student=user) & Q(with_draw=False)
                if is_search:
                    q = q & (Q(name__icontains=search_key) | Q(teacher__name__icontains=search_key))
                my_course = StudentCourse.objects.filter(q)
                if view_kind == "current":
                    course_list = [c.course for c in my_course if c.course.status < 4]
                elif view_kind == "withdraw":
                    course_list = [c.course for c in my_course if c.course.status == 2]
                elif view_kind == "is_end":
                    course_list = [c for c in my_course if c.course.status >= 4]
    
        else:
            return HttpResponse(INVALID_REQUEST_METHOD)
    
        context = {
            'info': info,
            'view_kind': view_kind,
            'course_list': course_list
        }
        if is_search:
            context["search_key"] = search_key
    
        return render(request, 'course/student/home.html', context)
    

    课程主页即学生的个人主页,故修改course/views.py中的原视图方法student_home

    def student_home(request):
        return redirect(reverse("view_course", kwargs={"view_kind": "current"}))
    

    2 - 选课撤课

    选课是新建一个学生课程关系记录,撤课则是修改对应的学生课程关系记录。
    即学生有两种操作课程方法,operate_kind如下:

    • select: 选课
    • withdraw: 撤课

    如果网页请求发送的方法不在这两种里面,则不符合规范,同时需要将这一信息通过响应返回告知浏览器。
    故在constants.py中添加ILLEGAL_KIND = "Illegal kind for you."

    course/views.py中,导入ILLEGAL_KIND,然后添加代码如下

    # 在开头导入timezone
    from django.utils import timezone
    
    def operate_course(request, operate_kind, course_id):
        """
        :param operate_kind:
            select: 选课
            withdraw: 撤课
        """
        user = get_user(request, "student")
        if not user:
            return redirect(reverse("login", kwargs={"kind": "student"}))
    
        if operate_kind not in ["select", "withdraw"]:
            return HttpResponse(ILLEGAL_KIND)
        elif operate_kind == "select":
            course = Course.objects.filter(pk=course_id).get()
            new_course = StudentCourse(student=user, course=course)
            new_course.save()
        elif operate_kind == "withdraw":
            q = Q(course__id=course_id) & Q(student=user) & Q(with_draw=False)
            course = StudentCourse.objects.filter(q).get()
            course.with_draw = True
            course.with_draw_time = timezone.now()
            course.save()
    
        return redirect(reverse("view_course", kwargs={"view_kind": operate_kind}))
    

    3 - 结课后评教

    学生给老师评教和老师给学生评分的后端逻辑是一样的,都是修改学生课程关系表内的数据。

    先在course/forms.py中添加

    class RateForm(forms.ModelForm):
        class Meta:
            model = StudentCourse
            fields = ["course", "scores", "comments", "rating", "assessment"]
    
        course = forms.CharField(label="课程", disabled=True)
        scores = forms.IntegerField(label="成绩", disabled=True)
        comments = forms.CharField(label="老师评价", disabled=True)
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.initial['course'] = self.instance.course
            self.initial['scores'] = self.instance.scores
            self.initial['comments'] = self.instance.comments
    
        def clean_course(self):
            return self.initial['course']
    
        def clean_scores(self):
            return self.initial['scores']
    
        def clean_comments(self):
            return self.initial['comments']
    

    然后添加模板文件templates/course/student/rating.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='location.href="{{ return_url }}"' />
                </div>
            </form>
        </div>
    {% endblock %}
    

    再在course/cbvs.py中导入RateForm类,然后添加代码如下

    class RateUpdateView(UpdateView):
        model = StudentCourse
        form_class = RateForm
        template_name = 'course/student/rating.html'
    
        def get(self, request, *args, **kwargs):
            self.object = self.get_object()
    
            info = {}
            return_url = reverse("view_course", kwargs={"view_kind": "is_end"})
            if self.object:
                student = self.object.student
                info = {
                    "name": student.name,
                    "kind": "student",
                }
    
            return self.render_to_response(self.get_context_data(info=info, return_url=return_url))
    
        def get_success_url(self):
            return reverse("view_course", kwargs={"view_kind": "is_end"})
    

    4 - 学生课程详情页

    这个使用CBVs实现起来最快
    先添加模板templates/course/student/course.html如下

    {% extends "course/nav.html" %}
    {% block title %}课程详情{% endblock %}
    {% block content %}
        <h3>课程详情</h3>
        <ul class="course-details">
            <li class="course-detail"><span class="detail-name">课程编号</span> {{ object.course.id }}</li>
            <li class="course-detail"><span class="detail-name">课程名</span> {{ object.course.name }}</li>
            <li class="course-detail"><span class="detail-name">学分</span> {{ object.course.credit }}</li>
            <li class="course-detail"><span class="detail-name">课程人数/最大人数</span> {{ object.course.get_current_count }}/{{ object.course.max_number }}</li>
            <li class="course-detail"><span class="detail-name">年份</span> {{ object.course.year }}</li>
            <li class="course-detail"><span class="detail-name">学期</span> {{ object.course.get_semester_display }}</li>
    
            <li class="course-detail"><span class="detail-name">教师</span> {{ object.course.teacher.name }}</li>
            <li class="course-detail"><span class="detail-name">上课时间</span>
                <span class="course-schedules">
                {% for schedule in object.course.get_schedules %}
                    <div class="course-schedule">{{ schedule }}</div>
                    <div class="course-schedule">{{ schedule }}</div>
                {% endfor %}
                </span>
            </li>
            <li class="course-detail"><span class="detail-name">得分</span>
                {% if object.scores != None %}{{ object.scores }}{% else %} - {% endif %}
            </li>
            <li class="course-detail"><span class="detail-name">评语</span>
                {% if object.comments != None %}{{ object.comments }}{% else %} - {% endif %}
            </li>
            <li class="course-detail"><span class="detail-name">学生评分</span>
                {% if object.rating != None %}{{ object.rating }}{% else %} - {% endif %}
            </li>
            <li class="course-detail"><span class="detail-name">学生评价</span>
                {% if object.assessment != None %}{{ object.assessment }}{% else %} - {% endif %}
            </li>
    
        </ul>
        <input type="button" value="返回" onclick='location.href="{% url 'view_course' 'is_end'%}"' />
    {% endblock %}
    

    再在course/cbvs.py中添加代码如下

    class StudentCourseDetailView(DetailView):
        model = StudentCourse
        template_name = 'course/student/course.html'
    
        def get(self, request, *args, **kwargs):
            self.object = self.get_object()
            context = self.get_context_data(object=self.object)
            if self.object:
                context["info"] = {
                    "name": self.object.student.name,
                    "kind": "student",
                }
            return self.render_to_response(context)
    

    5 - 添加路由

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

    from django.urls import path
    from course.views import *
    from course.cbvs import ScoreUpdateView, RateUpdateView, StudentCourseDetailView
    
    
    urlpatterns = [
        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"),
    
        path('student/view/<slug:view_kind>', view_course, name="view_course"),
        path('student/operate/<int:course_id>/<slug:operate_kind>', operate_course, name="operate_course"),
    
        path('student/evaluate/<int:pk>', RateUpdateView.as_view(), name="evaluate"),
        path('student/view_detail/<int:pk>', StudentCourseDetailView.as_view(), name="sview_detail"),
    ]
    

    6 - 效果

    选课页面

    当前课程页面

  • 相关阅读:
    c#: 传不确定个数参的方法
    导出Excel并设置样式
    无线网络国际会议排名
    初学Java接口
    初学Java修饰符
    [转]计算机类核心期刊投稿的一些资料汇总
    初学Java数据类型和变量
    初学Java数组
    初学Java运算符
    几个著名P2P会议与期刊及领军人物
  • 原文地址:https://www.cnblogs.com/BigShuang/p/14326848.html
Copyright © 2011-2022 走看看