心得管理

為了方便老師得知學生對每份作業的想法,從而了解學生對整個課程的感覺,因而設計了這個功能,讓系統依作業或依學生綜整相關作品的心得欄位。教師也可以針對每個學生的完整作業心得,評定一個成績。

修改資料模型

學生為每份作業所上傳的作品已包含了心得欄位,本章節的心得管理只需要將這些內容統整在同一個頁面上供教師參考即可。而整門課程的心得成績,則可直接在 Enroll 這個資料模型裡新增一個欄位來記錄之。

請修改 course/models.py 檔,插入第 22 行

class Enroll(Model): stu = ForeignKey(User, CASCADE) # 選修學生 course = ForeignKey(Course, CASCADE) # 選修課程 seat = IntegerField('座號', default=0) remark_score = IntegerField('心得成績', default=0)

新增路徑規則

預計要提供的功能如下:

功能 功能
學生心得列表 course/課程編號/remark/
查看學生完整心得 course/課程編號/remark/使用者編號/
查看作業完整心得 course/課程編號/remark/assignment/作業編號

修改課程應用程式的路徑規則檔 course/urls.py,新增第 19 - 23 行以及第 35 行

remark_urls = [ path('', RemarkUsers.as_view(), name='remark_users'), path('<int:uid>/', UserRemark.as_view(), name='user_remark'), path('assignment/<int:aid>/', AssignRemark.as_view(), name='remark_list'), ] urlpatterns = [ path('', CourseList.as_view(), name='course_list'), path('create/', CourseCreate.as_view(), name='course_create'), path('<int:cid>/', CourseView.as_view(), name='course_view'), path('<int:cid>/edit/', CourseEdit.as_view(), name='course_edit'), path('<int:cid>/enroll/', CourseEnroll.as_view(), name='course_enroll'), path('<int:cid>/users/', CourseUsers.as_view(), name='course_users'), path('<int:cid>/seat/', CourseEnrollSeat.as_view(), name='course_seat'), path('<int:cid>/msg/', include(msg_urlpatterns)), path('<int:cid>/assign/', include(assignment_urls)), path('<int:cid>/remark/', include(remark_urls)), ]

新增處理視圖

修改課程應用程式的視圖定義檔 course/views.py,新增以下視圖類別:

學生心得列表

class RemarkUsers(CourseAccessMixin, ListView): permission = COURSE_PERM_TEACHER template_name = 'course/remark_users.html' extra_context = {'title': '學生心得列表'} def get_queryset(self): return self.course.enroll_set\ .select_related('stu')\ .order_by('seat')

查看學生完整心得並評分

列出指定學生在本課程中所有作品的心得,並給予評分。

class UserRemark(CourseAccessMixin, UpdateView): permission = COURSE_PERM_TEACHER template_name = 'course/remark_score.html' extra_context = {'title': '查看學生心得'} model = Enroll fields = ['remark_score'] def get_object(self): return Enroll.objects.get( course = self.kwargs['cid'], stu = self.kwargs['uid'], ) def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx['assignment_list'] = Assignment.objects.filter( course_id = self.kwargs['cid'], ).annotate( remark = Subquery( Work.objects.filter( user = self.kwargs['uid'], assignment = OuterRef('id') ).values_list('memo').order_by('-id')[:1], ), ) ctx['stu'] = self.course.enroll_set.filter( stu=self.kwargs['uid'] ).values('seat', 'stu__first_name')[0] return ctx def get_success_url(self): return reverse('remark_users', args=[self.course.id])

查看作業完整心得

列出指定作業所有修課學生的心得。

class AssignRemark(CourseAccessMixin, ListView): permission = COURSE_PERM_TEACHER template_name = 'course/remark_list.html' extra_context = {'title': '查看作業心得'} def get_queryset(self): return self.course.enroll_set.annotate( remark = Subquery( Work.objects.filter( assignment_id = self.kwargs['aid'], user = OuterRef('stu'), ).values_list('memo').order_by('-id')[:1], ), ).order_by('seat').values('seat', 'stu__first_name', 'remark') def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx['atitle'] = Assignment.objects.get( id=self.kwargs['aid'] ).title return ctx

撰寫頁面範本

課程檢視頁面

修改課程檢視頁面範本 templates/course/course_detail.html,插入第 56 - 58 行,在教師的頁面上加上學生心得按鈕:

{% if course.teacher == user %} <div id="teacher_op" class="btn-group"> <a href="{% url 'course_msgbroadcast' course.id %}" class="{{ b2 }}"> <i class="fas fa-bullhorn"></i> 發布公告 </a> <a href="{% url 'remark_users' course.id %}" class="{{ b2 }}"> <i class="fas fa-lightbulb"></i> 學生心得 </a> </div> {% endif %}

學生心得列表

新增頁面範本 templates/course/remark_users.html,內容如下:

{% extends "course/course_detail.html" %} {% block course_detail_body %} <div id="work-list"> {% for stu in enroll_list %} <div class="work"> <span class="badge badge-light">{{ stu.seat }}</span> {% with cid=course.id sid=stu.stu_id %} {{ stu.stu.first_name }} <a href="{% url 'user_remark' cid sid %}" class="btn btn-sm btn-primary"> <i class="fas fa-search"></i> 查看心得 </a> {% endwith %} </div> {% endfor %} </div> {% endblock %}

查看學生完整心得並評分

新增頁面範本 templates/course/remark_score.html,內容如下:

{% extends "base.html" %} {% block content %} <div class="card"> <div class="card-header"> <h2> <span class="badge badge-primary"> {{ stu.seat }} </span> {{ stu.stu__first_name }} </h2> </div> <div class="card-body" id="work-list"> {% for a in assignment_list %} <div class="work"> <div class="assignment"> <span class="badge badge-primary"> {{ forloop.counter }} </span> <a href="{% url 'assignment_view' a.course_id a.id %}"> {{ a.title }} </a> </div> <div class="remark"> {% if a.remark %} {{ a.remark|linebreaksbr }} {% else %} <span class="badge badge-danger">未繳交</span> {% endif %} </div> </div> {% endfor %} </div> <div class="card-footer"> <form action="" method="post"> {% csrf_token %} {{ form }} <input type="submit" value="評分" class="btn btn-sm btn-primary"> </form> </div> </div> {% endblock %}

查看作業完整心得

新增頁面範本 templates/course/remark_list.html,內容如下:

{% extends "course/course_detail.html" %} {% block course_detail_body %} <h2>{{ atitle }}</h2> <div id="work-list"> {% for work in object_list %} <div class="work d-flex"> <div class="user-info mr-2"> <span class="badge badge-primary"> {{ work.seat }} {{ work.stu__first_name }} </span> </div> <div class="remark"> {% if work.remark %} {{ work.remark|linebreaksbr }} {% else %} <span class="badge badge-danger"> 尚未繳交 </span> {% endif %} </div> </div> {% endfor %} </div> {% endblock %}

另外,修改查看作業內容的頁面範本 templates/course/assignment_detail.html,新增第 14 - 16 行,加入「查看心得」按鈕:

{% if user.is_superuser or course.teacher == user %} <div> <a href="{% url 'assignment_edit' course.id assignment.id %}" class="btn btn-sm btn-primary"> 編輯作業 </a> <a href="{% url 'remark_list' course.id assignment.id %}" class="btn btn-sm btn-info"> 查看心得 </a> </div> {% endif %}