diff --git a/anatomy/views.py b/anatomy/views.py index ff01e1fd..0a4d07ce 100644 --- a/anatomy/views.py +++ b/anatomy/views.py @@ -248,7 +248,7 @@ def mark(request, exam_pk, sk, unmarked_exam_answers_only=True, review=False): elif not unmarked_exam_answers_only: mark_url = "anatomy:mark_all" - questions = exam.exam_questions.all().prefetch_related("answers") + questions = exam.get_questions().prefetch_related("answers") n = sk @@ -383,28 +383,28 @@ def mark(request, exam_pk, sk, unmarked_exam_answers_only=True, review=False): ) -@login_required -def exam_scores_refresh(request, pk): - exam = get_object_or_404(Exam, pk=pk) - - if not exam.exam_mode: - raise Http404("Packet not in exam mode") - - questions = exam.exam_questions.all() - - cids = UserAnswer.objects.filter(question__in=questions, exam__id=pk) - - # Force a score update - for c in cids: - c.get_answer_score(cached=False) - - return render( - request, - "anatomy/base.html", - { - "simple_content": "Answer scores updated", - }, - ) +#@login_required +#def exam_scores_refresh(request, pk): +# exam = get_object_or_404(Exam, pk=pk) +# +# if not exam.exam_mode: +# raise Http404("Packet not in exam mode") +# +# questions = exam.exam_questions.all() # Don't worry about order here +# +# cids = UserAnswer.objects.filter(question__in=questions, exam__id=pk) +# +# # Force a score update +# for c in cids: +# c.get_answer_score(cached=False) +# +# return render( +# request, +# "anatomy/base.html", +# { +# "simple_content": "Answer scores updated", +# }, +# ) def exam_scores_cid_user(request, pk, cid, passcode): @@ -416,7 +416,7 @@ def exam_scores_cid_user(request, pk, cid, passcode): if not exam.check_cid_user(cid, passcode, request.user): raise Http404("Error accessing exam") - questions = exam.exam_questions.all() + questions = exam.get_questions().prefetch_related("answers") answers_and_marks = [] answers_marks = [] @@ -615,13 +615,6 @@ class AnatomyQuestionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateV return context def form_valid(self, form): - - # save exam orders (there must be a better way to do this) - #exam_orders = {} - #for exam in self.object.exams.all(): - # exam_orders[exam] = list(exam.exam_questions.all()) - # print(exam_orders[exam]) - self.object = form.save(commit=False) self.object.save() diff --git a/atlas/views.py b/atlas/views.py index 1ebbf5ee..334b210f 100755 --- a/atlas/views.py +++ b/atlas/views.py @@ -759,11 +759,6 @@ class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateVi return context def form_valid(self, form): - # save exam orders (there must be a better way to do this) - # exam_orders = {} - # for exam in self.object.exams.all(): - # exam_orders[exam] = list(exam.exam_questions.all()) - self.object = form.save(commit=False) self.object.save() @@ -2407,12 +2402,6 @@ def collection_scores_cid(request, pk): cid_user_answers = CidReportAnswer.objects.filter(question__in=case_details) - # questions = exam.exam_questions.all().prefetch_related("answers") - - # cid_user_answers = CidReportAnswer.objects.select_related("question").filter( - # question__in=questions, exam__id=pk - # ) - cids = set() case_list = list(cases) diff --git a/generic/models.py b/generic/models.py index 9cdba312..9e7f55ef 100644 --- a/generic/models.py +++ b/generic/models.py @@ -886,7 +886,10 @@ class ExamBase(ExamOrCollectionGenericBase): # return super().clean(*args, **kwargs) def get_questions(self): - """Returns a list of questions in the exam in the correct order""" + """Returns a list of questions in the exam in the correct order + + This should be used in preference to exam_questions.all() as it + will order the questions correctly""" return self.exam_questions.all().order_by("examquestiondetail__sort_order") def order_questions(self): diff --git a/generic/templates/generic/exam_link_headers.html b/generic/templates/generic/exam_link_headers.html index 409ce296..f21dee48 100644 --- a/generic/templates/generic/exam_link_headers.html +++ b/generic/templates/generic/exam_link_headers.html @@ -6,6 +6,9 @@ \ Clone \ Authors {% endif %} +{% if can_edit and request.user.is_superuser %} + \ +{% endif %} {% if request.user.is_superuser %} - \ Admin Edit + Admin Edit {% endif %} \ No newline at end of file diff --git a/generic/views.py b/generic/views.py index 62dd11d0..979a766b 100644 --- a/generic/views.py +++ b/generic/views.py @@ -947,6 +947,7 @@ class ExamViews(View, LoginRequiredMixin): if not exam.exam_mode: raise Http404("Packet not in exam mode") + # We don't worry about order here questions = exam.exam_questions.all() cids = self.UserAnswer.objects.filter(question__in=questions, exam__id=pk) @@ -1304,7 +1305,7 @@ class ExamViews(View, LoginRequiredMixin): @method_decorator(login_required) def mark_overview(self, request, pk): - exam = get_object_or_404(self.Exam, pk=pk) + exam: ExamBase = get_object_or_404(self.Exam, pk=pk) if not exam.exam_mode: raise Http404("Packet not in exam mode") @@ -1343,7 +1344,7 @@ class ExamViews(View, LoginRequiredMixin): ) ) else: - questions = exam.exam_questions.all() + questions = exam.get_questions() # Handle exams that require double marking try: @@ -1416,8 +1417,6 @@ class ExamViews(View, LoginRequiredMixin): def exam_question_user_answer(self, request, pk: int, sk: int, c_or_u: str, user_or_cid: str): exam: ExamBase = get_object_or_404(self.Exam, pk=pk) - #question = exam.exam_questions.all()[sk] - if c_or_u == "u": user = get_object_or_404(User,pk=user_or_cid) answer = exam.get_question_user_user_answer(sk, user) @@ -1434,8 +1433,6 @@ class ExamViews(View, LoginRequiredMixin): def exam_question_cid_user_answer(self, request, pk: int, sk: int, cid: str): exam: ExamBase = get_object_or_404(self.Exam, pk=pk) - #question = exam.exam_questions.all()[sk] - cid_user = CidUser.objects.filter(cid=cid) answer =exam.get_question_cid_user_answer(sk, cid_user) @@ -1443,13 +1440,13 @@ class ExamViews(View, LoginRequiredMixin): @method_decorator(login_required) def exam_question_detail(self, request, pk, sk): - exam = get_object_or_404(self.Exam, pk=pk) + exam: ExamBase = get_object_or_404(self.Exam, pk=pk) if request.user not in exam.author.all(): if not self.check_user_access(request.user, pk): raise PermissionDenied - question = exam.exam_questions.all()[sk] + question = exam.get_questions()[sk] exam_length = len(exam.exam_questions.all()) @@ -1924,7 +1921,7 @@ class ExamViews(View, LoginRequiredMixin): return self.exam_scores_cid_user(request, pk, cid, user.passcode) def exam_scores_cid_user(self, request, pk, cid=None, passcode="", user=None): - exam = get_object_or_404(self.Exam, pk=pk) + exam: ExamBase = get_object_or_404(self.Exam, pk=pk) if not exam.exam_mode: raise Http404("Packet not in exam mode") @@ -1936,7 +1933,7 @@ class ExamViews(View, LoginRequiredMixin): request.user = user questions = ( - exam.exam_questions.all() + exam.get_questions() ) # .prefetch_related("cid_user_answers", "answers") # cid_user_answers = list(UserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question")) @@ -2080,7 +2077,7 @@ class ExamViews(View, LoginRequiredMixin): Returns: _type_: _description_ """ - exam = get_object_or_404(self.Exam, pk=pk) + exam: ExamBase = get_object_or_404(self.Exam, pk=pk) if not exam.exam_mode: raise Http404("Packet not in exam mode") @@ -2109,9 +2106,9 @@ class ExamViews(View, LoginRequiredMixin): if self.app_name in ("physics", "sbas", "longs"): cached_scores = False - questions = exam.exam_questions.all() + questions = exam.get_questions() else: - questions = exam.exam_questions.all().prefetch_related("answers") + questions = exam.get_questions().prefetch_related("answers") # We could prefect the UserAnswers.answers here (if we didn't cache them) cid_user_answers = self.UserAnswer.objects.select_related("question").filter( @@ -2315,6 +2312,7 @@ class ExamViews(View, LoginRequiredMixin): "mode": mode, "plot": fig_html, "cached_scores": cached_scores, + "can_edit": exam.check_user_can_edit(request.user), } if self.app_name == "rapids": @@ -2329,7 +2327,7 @@ class ExamViews(View, LoginRequiredMixin): ) def exam_stats(self, request, exam_id): - exam = get_object_or_404(self.Exam, pk=exam_id) + exam: ExamBase = get_object_or_404(self.Exam, pk=exam_id) if not exam.exam_mode: raise Http404("Packet not in exam mode") @@ -2366,7 +2364,7 @@ class GenericViewBase: """ Return a json representation of the question when the exam is published """ - exam = get_object_or_404(self.exam_object, pk=pk) + exam: ExamBase = get_object_or_404(self.exam_object, pk=pk) print(request.POST["question_number"]) print(type(request.POST["question_number"])) @@ -2374,7 +2372,7 @@ class GenericViewBase: if not exam.publish_results: raise Http404 - question = exam.exam_questions.all()[int(request.POST["question_number"])] + question = exam.get_questions()[int(request.POST["question_number"])] question_json = question.get_question_json(based=False, feedback=True) return JsonResponse(question_json) diff --git a/longs/templates/longs/exam_scores.html b/longs/templates/longs/exam_scores.html index b389e1d7..1372346c 100644 --- a/longs/templates/longs/exam_scores.html +++ b/longs/templates/longs/exam_scores.html @@ -1,10 +1,15 @@ {% extends 'generic/exam_scores_base.html' %} +{% block navigation %} + {{ block.super }} + {% include 'generic/exam_link_headers.html' %} +{% endblock navigation %} + {% block table_answers %} {% for question in questions %}