diff --git a/physics/views.py b/physics/views.py index 1c1cb21f..00e6f585 100644 --- a/physics/views.py +++ b/physics/views.py @@ -42,7 +42,12 @@ import json import statistics import plotly.express as px -from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews, GenericViewBase +from generic.views import ( + AuthorRequiredMixin, + ExamCloneMixin, + ExamViews, + GenericViewBase, +) from rest_framework import viewsets, permissions from rest_framework.pagination import PageNumberPagination @@ -311,7 +316,7 @@ def exam_take(request, pk, sk, cid, passcode): ) -#def loadJsonAnswer(answer): +# def loadJsonAnswer(answer): # # As access is not restricted make sure the data appears valid # if (not isinstance(answer["cid"], int)) or (not isinstance(answer["eid"], int)): # return False, JsonResponse({"success": False, "error": "invalid"}) @@ -368,9 +373,7 @@ def exam_take(request, pk, sk, cid, passcode): # return True, None -GenericExamViews = ExamViews( - Exam, Question, None, CidUserAnswer, "physics", "physics" -) +GenericExamViews = ExamViews(Exam, Question, None, CidUserAnswer, "physics", "physics") GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam) @@ -391,10 +394,13 @@ class ExamClone(AuthorOrCheckerRequiredMixin, ExamCloneMixin, ExamCreate): """Clone exam view""" -class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView): +class ExamAuthorUpdate( + RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView +): model = Exam form_class = ExamAuthorForm + class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView): model = Exam template_name = "exam_confirm_delete.html" diff --git a/rapids/views.py b/rapids/views.py index afd5d362..61984fea 100755 --- a/rapids/views.py +++ b/rapids/views.py @@ -42,7 +42,12 @@ from .models import ( CidUserAnswer, ) -from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews, GenericViewBase +from generic.views import ( + AuthorRequiredMixin, + ExamCloneMixin, + ExamViews, + GenericViewBase, +) from reversion.views import RevisionMixin @@ -350,8 +355,8 @@ class RapidUpdate( 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 = {} + # for exam in self.object.exams.all(): # exam_orders[exam] = list(exam.exam_questions.all()) self.object = form.save(commit=False) @@ -371,8 +376,8 @@ class RapidUpdate( answer_formset.save() # restore exam orders - #wanted_exams = form["exams"].data - #for exam in self.object.exams.all(): + # wanted_exams = form["exams"].data + # for exam in self.object.exams.all(): # if exam in exam_orders and self.object in exam_orders[exam]: # print(exam_orders[exam]) # exam.exam_questions.set(exam_orders[exam]) @@ -509,7 +514,6 @@ class RapidView(LoginRequiredMixin, SingleTableMixin, FilterView): filterset_class = RapidFilter - @login_required def mark_all(request, exam_pk, sk): return mark(request, exam_pk, sk, unmarked_exam_answers_only=False) @@ -673,7 +677,6 @@ def mark(request, exam_pk, sk, unmarked_exam_answers_only=True, review=False): ) - def exam_scores_cid_user(request, pk, cid, passcode): exam = get_object_or_404(Exam, pk=pk) @@ -682,13 +685,15 @@ def exam_scores_cid_user(request, pk, cid, passcode): # TODO:Need some kind of test for cid - questions = exam.exam_questions.all()#.prefetch_related("cid_user_answers", "answers") + questions = ( + exam.exam_questions.all() + ) # .prefetch_related("cid_user_answers", "answers") - #cid_user_answers = list(CidUserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question")) + # cid_user_answers = list(CidUserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question")) - #cid_user_answers_q_map = {} + # cid_user_answers_q_map = {} - #for ans in cid_user_answers: + # for ans in cid_user_answers: # cid_user_answers_q_map[ans.question] = ans answers_and_marks = [] @@ -702,7 +707,7 @@ def exam_scores_cid_user(request, pk, cid, passcode): for q in questions: # Get user answer user_answer = q.cid_user_answers.filter(cid=cid, exam__id=pk).first() - #user_answer = cid_user_answers_q_map[q] + # user_answer = cid_user_answers_q_map[q] if not user_answer or user_answer is None: # skip if no answer @@ -762,9 +767,7 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView): success_url = reverse_lazy("rapids:rapid_view") -GenericExamViews = ExamViews( - Exam, Rapid, Answer, CidUserAnswer, "rapids", "rapid" -) +GenericExamViews = ExamViews(Exam, Rapid, Answer, CidUserAnswer, "rapids", "rapid") class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView): @@ -793,18 +796,24 @@ class ExamUpdate( return super().form_valid(form) -class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView): + +class ExamAuthorUpdate( + RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView +): model = Exam form_class = ExamAuthorForm + class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView): model = Exam template_name = "exam_confirm_delete.html" success_url = reverse_lazy("rapids:index") + class UserAnswerView(LoginRequiredMixin, DetailView): model = CidUserAnswer + class UserAnswerTableView(LoginRequiredMixin, SingleTableMixin, FilterView): model = CidUserAnswer table_class = RapidUserAnswerTable @@ -921,6 +930,7 @@ class RapidLateralityViewSet( GenericViews = GenericViewBase("rapids", Rapid, CidUserAnswer, Exam) + @user_is_author_or_rapid_checker def question_anonymise_dicom(request, pk): question = get_object_or_404(Rapid, pk=pk) @@ -929,6 +939,7 @@ def question_anonymise_dicom(request, pk): return redirect("rapids:question_detail", pk=pk) + @user_is_author_or_rapid_checker def question_save_annotation(request, pk): if request.is_ajax() and request.method == "POST":