def get_students_problem_grades(request, csv=False): """ Get a list of students and grades for a particular problem. If 'csv' is False, returns a dict of student's name: username: grade: percent. If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames, grades, percents for CSV download. """ module_state_key = Location.from_deprecated_string(request.GET.get('module_id')) csv = request.GET.get('csv') # Query for "problem grades" students students = models.StudentModule.objects.select_related('student').filter( module_state_key=module_state_key, module_type__exact='problem', grade__isnull=False, ).values('student__username', 'student__profile__name', 'grade', 'max_grade').order_by('student__profile__name') results = [] if not csv: # Restrict screen list length # Adding 1 so can tell if list is larger than MAX_SCREEN_LIST_LENGTH # without doing another select. for student in students[0:MAX_SCREEN_LIST_LENGTH + 1]: student_dict = { 'name': student['student__profile__name'], 'username': student['student__username'], 'grade': student['grade'], } student_dict['percent'] = 0 if student['max_grade'] > 0: student_dict['percent'] = round(student['grade'] * 100 / student['max_grade']) results.append(student_dict) max_exceeded = False if len(results) > MAX_SCREEN_LIST_LENGTH: # Remove the last item so list length is exactly MAX_SCREEN_LIST_LENGTH del results[-1] max_exceeded = True response_payload = { 'results': results, 'max_exceeded': max_exceeded, } return JsonResponse(response_payload) else: tooltip = request.GET.get('tooltip') filename = sanitize_filename(tooltip[:tooltip.rfind(' - ')]) header = [_("Name").encode('utf-8'), _("Username").encode('utf-8'), _("Grade").encode('utf-8'), _("Percent").encode('utf-8')] for student in students: percent = 0 if student['max_grade'] > 0: percent = round(student['grade'] * 100 / student['max_grade']) results.append([student['student__profile__name'], student['student__username'], student['grade'], percent]) response = create_csv_response(filename, header, results) return response
def get_students_problem_grades(request, csv=False): """ Get a list of students and grades for a particular problem. If 'csv' is False, returns a dict of student's name: username: grade: percent. If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames, grades, percents for CSV download. """ module_id = request.GET.get('module_id') csv = request.GET.get('csv') # Query for "problem grades" students students = models.StudentModule.objects.select_related('student').filter( module_state_key__exact=module_id, module_type__exact='problem', grade__isnull=False, ).values('student__username', 'student__profile__name', 'grade', 'max_grade').order_by('student__profile__name') results = [] if not csv: # Restrict screen list length # Adding 1 so can tell if list is larger than MAX_SCREEN_LIST_LENGTH # without doing another select. for student in students[0:MAX_SCREEN_LIST_LENGTH + 1]: student_dict = { 'name': student['student__profile__name'], 'username': student['student__username'], 'grade': student['grade'], } student_dict['percent'] = 0 if student['max_grade'] > 0: student_dict['percent'] = round(student['grade'] * 100 / student['max_grade']) results.append(student_dict) max_exceeded = False if len(results) > MAX_SCREEN_LIST_LENGTH: # Remove the last item so list length is exactly MAX_SCREEN_LIST_LENGTH del results[-1] max_exceeded = True response_payload = { 'results': results, 'max_exceeded': max_exceeded, } return JsonResponse(response_payload) else: tooltip = request.GET.get('tooltip') filename = sanitize_filename(tooltip[:tooltip.rfind(' - ')]) header = [_("Name").encode('utf-8'), _("Username").encode('utf-8'), _("Grade").encode('utf-8'), _("Percent").encode('utf-8')] for student in students: percent = 0 if student['max_grade'] > 0: percent = round(student['grade'] * 100 / student['max_grade']) results.append([student['student__profile__name'], student['student__username'], student['grade'], percent]) response = create_csv_response(filename, header, results) return response
def test_create_csv_response(self): header = ['Name', 'Email'] datarows = [['Jim', '*****@*****.**'], ['Jake', '*****@*****.**'], ['Jeeves', '*****@*****.**']] res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '"Name","Email"\r\n"Jim","*****@*****.**"\r\n"Jake","*****@*****.**"\r\n"Jeeves","*****@*****.**"')
def test_create_csv_response_empty(self): header = [] datarows = [] res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '')
def get_students_opened_subsection(request, csv=False): """ Get a list of students that opened a particular subsection. If 'csv' is False, returns a dict of student's name: username. If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames for CSV download. """ module_state_key = Location.from_deprecated_string( request.GET.get('module_id')) csv = request.GET.get('csv') # Query for "opened a subsection" students students = models.StudentModule.objects.select_related('student').filter( module_state_key__exact=module_state_key, module_type__exact='sequential', ).values('student__username', 'student__profile__name').order_by('student__profile__name') results = [] if not csv: # Restrict screen list length # Adding 1 so can tell if list is larger than MAX_SCREEN_LIST_LENGTH # without doing another select. for student in students[0:MAX_SCREEN_LIST_LENGTH + 1]: results.append({ 'name': student['student__profile__name'], 'username': student['student__username'], }) max_exceeded = False if len(results) > MAX_SCREEN_LIST_LENGTH: # Remove the last item so list length is exactly MAX_SCREEN_LIST_LENGTH del results[-1] max_exceeded = True response_payload = { 'results': results, 'max_exceeded': max_exceeded, } return JsonResponse(response_payload) else: tooltip = request.GET.get('tooltip') # Subsection name is everything after 3rd space in tooltip filename = sanitize_filename(' '.join(tooltip.split(' ')[3:])) header = [_("Name").encode('utf-8'), _("Username").encode('utf-8')] for student in students: results.append([ student['student__profile__name'], student['student__username'] ]) response = create_csv_response(filename, header, results) return response
def test_create_csv_response(self): header = ['Name', 'Email'] datarows = [['Jim', '*****@*****.**'], ['Jake', '*****@*****.**'], ['Jeeves', '*****@*****.**']] res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) self.assertEqual( res.content.strip(), '"Name","Email"\r\n"Jim","*****@*****.**"\r\n"Jake","*****@*****.**"\r\n"Jeeves","*****@*****.**"' )
def get_students_opened_subsection(request, csv=False): """ Get a list of students that opened a particular subsection. If 'csv' is False, returns a dict of student's name: username. If 'csv' is True, returns a header array, and an array of arrays in the format: student names, usernames for CSV download. """ module_id = request.GET.get('module_id') csv = request.GET.get('csv') # Query for "opened a subsection" students students = models.StudentModule.objects.select_related('student').filter( module_state_key__exact=module_id, module_type__exact='sequential', ).values('student__username', 'student__profile__name').order_by('student__profile__name') results = [] if not csv: # Restrict screen list length # Adding 1 so can tell if list is larger than MAX_SCREEN_LIST_LENGTH # without doing another select. for student in students[0:MAX_SCREEN_LIST_LENGTH + 1]: results.append({ 'name': student['student__profile__name'], 'username': student['student__username'], }) max_exceeded = False if len(results) > MAX_SCREEN_LIST_LENGTH: # Remove the last item so list length is exactly MAX_SCREEN_LIST_LENGTH del results[-1] max_exceeded = True response_payload = { 'results': results, 'max_exceeded': max_exceeded, } return JsonResponse(response_payload) else: tooltip = request.GET.get('tooltip') # Subsection name is everything after 3rd space in tooltip filename = sanitize_filename(' '.join(tooltip.split(' ')[3:])) header = [_("Name").encode('utf-8'), _("Username").encode('utf-8')] for student in students: results.append([student['student__profile__name'], student['student__username']]) response = create_csv_response(filename, header, results) return response
def post_metrics_data_csv(request): """ Generate a list of opened subsections or problems for the entire course for CSV download. Returns a header array, and an array of arrays in the format: section, subsection, count of students for subsections or section, problem, name, count of students, percent of students, score for problems. """ data = json.loads(request.POST['data']) sections = json.loads(data['sections']) tooltips = json.loads(data['tooltips']) course_id = data['course_id'] data_type = data['data_type'] results = [] if data_type == 'subsection': header = [_("Section").encode('utf-8'), _("Subsection").encode('utf-8'), _("Opened by this number of students").encode('utf-8')] filename = sanitize_filename(_('subsections') + '_' + course_id) elif data_type == 'problem': header = [_("Section").encode('utf-8'), _("Problem").encode('utf-8'), _("Name").encode('utf-8'), _("Count of Students").encode('utf-8'), _("% of Students").encode('utf-8'), _("Score").encode('utf-8')] filename = sanitize_filename(_('problems') + '_' + course_id) for index, section in enumerate(sections): results.append([section]) # tooltips array is array of dicts for subsections and # array of array of dicts for problems. if data_type == 'subsection': for tooltip_dict in tooltips[index]: num_students = tooltip_dict['num_students'] subsection = tooltip_dict['subsection_name'] # Append to results offsetting 1 column to the right. results.append(['', subsection, num_students]) elif data_type == 'problem': for tooltip in tooltips[index]: for tooltip_dict in tooltip: label = tooltip_dict['label'] problem_name = tooltip_dict['problem_name'] count_grade = tooltip_dict['count_grade'] student_count_percent = tooltip_dict['student_count_percent'] percent = tooltip_dict['percent'] # Append to results offsetting 1 column to the right. results.append(['', label, problem_name, count_grade, student_count_percent, percent]) response = create_csv_response(filename, header, results) return response
def post_metrics_data_csv(request): """ Generate a list of opened subsections or problems for the entire course for CSV download. Returns a header array, and an array of arrays in the format: section, subsection, count of students for subsections or section, problem, name, count of students, percent of students, score for problems. """ data = json.loads(request.POST['data']) sections = json.loads(data['sections']) tooltips = json.loads(data['tooltips']) course_id = data['course_id'] data_type = data['data_type'] results = [] if data_type == 'subsection': header = [_("Section").encode('utf-8'), _("Subsection").encode('utf-8'), _("Opened by this number of students").encode('utf-8')] filename = sanitize_filename(_('subsections') + '_' + course_id) elif data_type == 'problem': header = [_("Section").encode('utf-8'), _("Problem").encode('utf-8'), _("Name").encode('utf-8'), _("Count of Students").encode('utf-8'), _("Percent of Students").encode('utf-8'), _("Score").encode('utf-8')] filename = sanitize_filename(_('problems') + '_' + course_id) for index, section in enumerate(sections): results.append([section]) # tooltips array is array of dicts for subsections and # array of array of dicts for problems. if data_type == 'subsection': for tooltip_dict in tooltips[index]: num_students = tooltip_dict['num_students'] subsection = tooltip_dict['subsection_name'] # Append to results offsetting 1 column to the right. results.append(['', subsection, num_students]) elif data_type == 'problem': for tooltip in tooltips[index]: for tooltip_dict in tooltip: label = tooltip_dict['label'] problem_name = tooltip_dict['problem_name'] count_grade = tooltip_dict['count_grade'] student_count_percent = tooltip_dict['student_count_percent'] percent = tooltip_dict['percent'] # Append to results offsetting 1 column to the right. results.append(['', label, problem_name, count_grade, student_count_percent, percent]) response = create_csv_response(filename, header, results) return response