diff options
Diffstat (limited to 'yaksh')
-rw-r--r-- | yaksh/models.py | 38 | ||||
-rw-r--r-- | yaksh/views.py | 110 |
2 files changed, 62 insertions, 86 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index 2978f43..984a712 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -992,13 +992,13 @@ class Course(models.Model): return self.rejected.all() def is_enrolled(self, user): - return user in self.students.all() + return self.students.filter(id=user.id).exists() def is_creator(self, user): return self.creator == user def is_teacher(self, user): - return True if user in self.teachers.all() else False + return self.teachers.filter(id=user.id).exists() def is_self_enroll(self): return True if self.enrollment == enrollment_methods[1][0] else False @@ -1062,7 +1062,7 @@ class Course(models.Model): return success def get_only_students(self): - teachers = list(self.teachers.all().values_list("id", flat=True)) + teachers = list(self.teachers.values_list("id", flat=True)) teachers.append(self.creator.id) students = self.students.exclude(id__in=teachers) return students @@ -1181,7 +1181,7 @@ class Course(models.Model): return percentage def is_student(self, user): - return user in self.students.all() + return self.students.filter(id=user.id).exists() def create_zip(self, path, static_files): zip_file_name = string_io() @@ -2212,15 +2212,27 @@ class AnswerPaper(models.Model): 'attempt_number', "course" ) - def get_per_question_score(self, question_id): - questions = self.get_questions().values_list('id', flat=True) - if question_id not in questions: - return 'NA' - answer = self.get_latest_answer(question_id) - if answer: - return answer.marks - else: - return 0 + def get_per_question_score(self, question_ids): + que_ids = list(zip(*question_ids))[1] + answers = self.answers.filter( + question_id__in=que_ids).values("question_id", "marks") + que_data = {} + df = pd.DataFrame(answers) + ans_data = None + if not df.empty: + ans_data = df.groupby("question_id").tail(1) + for que_summary, que_id in question_ids: + if ans_data is not None: + ans = ans_data['question_id'].to_list() + marks = ans_data['marks'].to_list() + if que_id in ans: + idx = ans.index(que_id) + que_data[que_summary] = marks[idx] + else: + que_data[que_summary] = 0 + else: + que_data[que_summary] = 0 + return que_data def current_question(self): """Returns the current active question to display.""" diff --git a/yaksh/views.py b/yaksh/views.py index 11a77b8..dc4f833 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -26,6 +26,7 @@ from textwrap import dedent import zipfile import markdown import ruamel +import pandas as pd try: from StringIO import StringIO as string_io except ImportError: @@ -80,7 +81,10 @@ def is_moderator(user, group_name=MOD_GROUP_NAME): """Check if the user is having moderator rights""" try: group = Group.objects.get(name=group_name) - return user.profile.is_moderator and user in group.user_set.all() + return ( + user.profile.is_moderator and + group.user_set.filter(id=user.id).exists() + ) except Profile.DoesNotExist: return False except Group.DoesNotExist: @@ -703,7 +707,7 @@ def show_question(request, question, paper, error_message=None, ) else: quiz_type = 'Exercise' - if question in paper.questions_answered.all(): + if paper.questions_answered.filter(id=question.id).exists(): notification = ( 'You have already attempted this question successfully' if question.type == "code" else @@ -1837,80 +1841,40 @@ def download_quiz_csv(request, course_id, quiz_id): if not course.is_creator(current_user) and \ not course.is_teacher(current_user): raise Http404('The quiz does not belong to your course') - users = course.get_enrolled().order_by('first_name') - if not users: - return monitor(request, quiz_id) - csv_fields = [] - attempt_number = None question_paper = quiz.questionpaper_set.last() - last_attempt_number = AnswerPaper.objects.get_attempt_numbers( - question_paper.id, course.id).last() if request.method == 'POST': csv_fields = request.POST.getlist('csv_fields') - attempt_number = request.POST.get('attempt_number', - last_attempt_number) - if not csv_fields: - csv_fields = CSV_FIELDS - if not attempt_number: - attempt_number = last_attempt_number - - questions = question_paper.get_question_bank() - answerpapers = AnswerPaper.objects.filter( - question_paper=question_paper, - attempt_number=attempt_number, course_id=course_id) - if not answerpapers: - return monitor(request, quiz_id, course_id) - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = \ - 'attachment; filename="{0}-{1}-attempt{2}.csv"'.format( - course.name.replace('.', ''), quiz.description.replace('.', ''), - attempt_number) - writer = csv.writer(response) - if 'questions' in csv_fields: - csv_fields = _expand_questions(questions, csv_fields) - writer.writerow(csv_fields) - - csv_fields_values = { - 'name': 'user.get_full_name().title()', - 'roll_number': 'user.profile.roll_number', - 'institute': 'user.profile.institute', - 'department': 'user.profile.department', - 'username': 'user.username', - 'marks_obtained': 'answerpaper.marks_obtained', - 'out_of': 'question_paper.total_marks', - 'percentage': 'answerpaper.percent', - 'status': 'answerpaper.status'} - questions_scores = {} - for question in questions: - questions_scores['Q-{0}-{1}-{2}-marks'.format( - question.id, question.summary, question.points)] \ - = 'answerpaper.get_per_question_score({0})'.format(question.id) - answer = question.answer_set.last() - comment = None - if answer: - comment = answer.comment - else: - comment = '' - questions_scores['Q-{0}-{1}-comments'.format( - question.id, question.summary)] \ - = 'answerpaper.get_answer_comment({0})'.format(question.id) - csv_fields_values.update(questions_scores) - - users = users.exclude(id=course.creator.id).exclude( - id__in=course.teachers.all()) - for user in users: - row = [] - answerpaper = None - papers = answerpapers.filter(user=user) - if papers: - answerpaper = papers.first() - for field in csv_fields: - try: - row.append(eval(csv_fields_values[field])) - except AttributeError: - row.append('-') - writer.writerow(row) - return response + attempt_number = request.POST.get('attempt_number') + questions = question_paper.get_question_bank() + answerpapers = AnswerPaper.objects.select_related( + "user").select_related('question_paper').prefetch_related( + 'answers').filter( + course_id=course_id, question_paper_id=question_paper.id, + attempt_number=attempt_number + ).order_by("user__first_name") + que_summaries = [ + (f"{que.summary}-{que.points}-marks", que.id) for que in questions + ] + user_data = list(answerpapers.values( + "user__first_name", "user__last_name", + "user__profile__roll_number", "user__profile__institute", + "user__profile__department", "marks_obtained", + "question_paper__total_marks", "percent", "status" + )) + for idx, ap in enumerate(answerpapers): + que_data = ap.get_per_question_score(que_summaries) + user_data[idx].update(que_data) + df = pd.DataFrame(user_data) + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = \ + 'attachment; filename="{0}-{1}-attempt-{2}.csv"'.format( + course.name.replace(' ', '_'), + quiz.description.replace(' ', '_'), attempt_number + ) + output_file = df.to_csv(response, index=False) + return response + else: + return monitor(request, quiz_id) @login_required |