231 lines
7.7 KiB
Python
231 lines
7.7 KiB
Python
# Grading Views
|
|
|
|
import logging
|
|
import urllib
|
|
|
|
from django.conf import settings
|
|
from django.views.decorators.cache import cache_control
|
|
from mitxmako.shortcuts import render_to_response
|
|
from django.core.urlresolvers import reverse
|
|
|
|
from student.models import unique_id_for_user
|
|
from courseware.courses import get_course_with_access
|
|
|
|
from peer_grading_service import PeerGradingService
|
|
from peer_grading_service import MockPeerGradingService
|
|
from controller_query_service import ControllerQueryService
|
|
from grading_service import GradingServiceError
|
|
import json
|
|
from .staff_grading import StaffGrading
|
|
from student.models import unique_id_for_user
|
|
|
|
import open_ended_util
|
|
import open_ended_notifications
|
|
|
|
from xmodule.modulestore.django import modulestore
|
|
from xmodule.modulestore import search
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
template_imports = {'urllib': urllib}
|
|
if settings.MOCK_PEER_GRADING:
|
|
peer_gs = MockPeerGradingService()
|
|
else:
|
|
peer_gs = PeerGradingService(settings.PEER_GRADING_INTERFACE)
|
|
|
|
controller_url = open_ended_util.get_controller_url()
|
|
controller_qs = ControllerQueryService(controller_url)
|
|
|
|
"""
|
|
Reverses the URL from the name and the course id, and then adds a trailing slash if
|
|
it does not exist yet
|
|
|
|
"""
|
|
def _reverse_with_slash(url_name, course_id):
|
|
ajax_url = _reverse_without_slash(url_name, course_id)
|
|
if not ajax_url.endswith('/'):
|
|
ajax_url += '/'
|
|
return ajax_url
|
|
|
|
def _reverse_without_slash(url_name, course_id):
|
|
ajax_url = reverse(url_name, kwargs={'course_id': course_id})
|
|
return ajax_url
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
def staff_grading(request, course_id):
|
|
"""
|
|
Show the instructor grading interface.
|
|
"""
|
|
course = get_course_with_access(request.user, course_id, 'staff')
|
|
|
|
ajax_url = _reverse_with_slash('staff_grading', course_id)
|
|
|
|
return render_to_response('instructor/staff_grading.html', {
|
|
'course': course,
|
|
'course_id': course_id,
|
|
'ajax_url': ajax_url,
|
|
# Checked above
|
|
'staff_access': True, })
|
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
def peer_grading(request, course_id):
|
|
'''
|
|
Show a peer grading interface
|
|
'''
|
|
course = get_course_with_access(request.user, course_id, 'load')
|
|
|
|
# call problem list service
|
|
success = False
|
|
error_text = ""
|
|
problem_list = []
|
|
try:
|
|
problem_list_json = peer_gs.get_problem_list(course_id, unique_id_for_user(request.user))
|
|
problem_list_dict = json.loads(problem_list_json)
|
|
success = problem_list_dict['success']
|
|
if 'error' in problem_list_dict:
|
|
error_text = problem_list_dict['error']
|
|
|
|
problem_list = problem_list_dict['problem_list']
|
|
|
|
except GradingServiceError:
|
|
error_text = "Error occured while contacting the grading service"
|
|
success = False
|
|
# catch error if if the json loads fails
|
|
except ValueError:
|
|
error_text = "Could not get problem list"
|
|
success = False
|
|
|
|
ajax_url = _reverse_with_slash('peer_grading', course_id)
|
|
|
|
return render_to_response('peer_grading/peer_grading.html', {
|
|
'course': course,
|
|
'course_id': course_id,
|
|
'ajax_url': ajax_url,
|
|
'success': success,
|
|
'problem_list': problem_list,
|
|
'error_text': error_text,
|
|
# Checked above
|
|
'staff_access': False, })
|
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
def peer_grading_problem(request, course_id):
|
|
'''
|
|
Show individual problem interface
|
|
'''
|
|
course = get_course_with_access(request.user, course_id, 'load')
|
|
problem_location = request.GET.get("location")
|
|
|
|
ajax_url = _reverse_with_slash('peer_grading', course_id)
|
|
|
|
return render_to_response('peer_grading/peer_grading_problem.html', {
|
|
'view_html': '',
|
|
'course': course,
|
|
'problem_location': problem_location,
|
|
'course_id': course_id,
|
|
'ajax_url': ajax_url,
|
|
# Checked above
|
|
'staff_access': False, })
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
def student_problem_list(request, course_id):
|
|
'''
|
|
Show a student problem list
|
|
'''
|
|
course = get_course_with_access(request.user, course_id, 'load')
|
|
student_id = unique_id_for_user(request.user)
|
|
|
|
# call problem list service
|
|
success = False
|
|
error_text = ""
|
|
problem_list = []
|
|
base_course_url = reverse('courses')
|
|
|
|
try:
|
|
problem_list_json = controller_qs.get_grading_status_list(course_id, unique_id_for_user(request.user))
|
|
problem_list_dict = json.loads(problem_list_json)
|
|
success = problem_list_dict['success']
|
|
if 'error' in problem_list_dict:
|
|
error_text = problem_list_dict['error']
|
|
|
|
problem_list = problem_list_dict['problem_list']
|
|
|
|
for i in xrange(0,len(problem_list)):
|
|
problem_url_parts = search.path_to_location(modulestore(), course.id, problem_list[i]['location'])
|
|
problem_url = base_course_url + "/"
|
|
for z in xrange(0,len(problem_url_parts)):
|
|
part = problem_url_parts[z]
|
|
if part is not None:
|
|
if z==1:
|
|
problem_url += "courseware/"
|
|
problem_url += part + "/"
|
|
|
|
problem_list[i].update({'actual_url' : problem_url})
|
|
|
|
except GradingServiceError:
|
|
error_text = "Error occured while contacting the grading service"
|
|
success = False
|
|
# catch error if if the json loads fails
|
|
except ValueError:
|
|
error_text = "Could not get problem list"
|
|
success = False
|
|
|
|
ajax_url = _reverse_with_slash('open_ended_problems', course_id)
|
|
|
|
return render_to_response('open_ended_problems/open_ended_problems.html', {
|
|
'course': course,
|
|
'course_id': course_id,
|
|
'ajax_url': ajax_url,
|
|
'success': success,
|
|
'problem_list': problem_list,
|
|
'error_text': error_text,
|
|
# Checked above
|
|
'staff_access': False, })
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
def combined_notifications(request, course_id):
|
|
course = get_course_with_access(request.user, course_id, 'load')
|
|
user = request.user
|
|
notifications = open_ended_notifications.combined_notifications(course, user)
|
|
log.debug(notifications)
|
|
response = notifications['response']
|
|
notification_tuples=open_ended_notifications.NOTIFICATION_TYPES
|
|
|
|
notification_list = []
|
|
description_dict = {
|
|
'Peer Grading': "View all problems that require peer assessment in this particular course.",
|
|
'Staff Grading': "View ungraded submissions submitted by your students for the open ended problems in the course.",
|
|
'Problems you have submitted': "View open ended problems that you have previously submitted for grading."
|
|
}
|
|
for response_num in xrange(0,len(notification_tuples)):
|
|
tag=notification_tuples[response_num][0]
|
|
if tag in response:
|
|
url_name = notification_tuples[response_num][1]
|
|
human_name = notification_tuples[response_num][2]
|
|
url = _reverse_without_slash(url_name, course_id)
|
|
has_img = response[tag]
|
|
|
|
notification_item = {
|
|
'url' : url,
|
|
'name' : human_name,
|
|
'alert' : has_img,
|
|
'description': description_dict[human_name]
|
|
}
|
|
notification_list.append(notification_item)
|
|
|
|
ajax_url = _reverse_with_slash('open_ended_notifications', course_id)
|
|
combined_dict = {
|
|
'error_text' : "",
|
|
'notification_list' : notification_list,
|
|
'course' : course,
|
|
'success' : True,
|
|
'ajax_url' : ajax_url,
|
|
}
|
|
|
|
return render_to_response('open_ended_problems/combined_notifications.html',
|
|
combined_dict
|
|
)
|
|
|
|
|