This commit is contained in:
Ross
2021-12-11 00:21:44 +00:00
parent 38d1fcf485
commit 2cadc94e48
2 changed files with 31 additions and 19 deletions
-3
View File
@@ -116,9 +116,6 @@
//$("ul.physics-answer-list li[data-ans='{{question.best_answer}}']").addClass("correct"); //$("ul.physics-answer-list li[data-ans='{{question.best_answer}}']").addClass("correct");
{% endif %} {% endif %}
{% comment %} {% if saved_answer %}
$("ul.physics-answer-list li[data-ans='{{saved_answer}}']").addClass("selected"); {% endif %} {% endcomment %}
for (let i = 0; i < {{ exam_length }}; i++) { for (let i = 0; i < {{ exam_length }}; i++) {
$("#menu-list").append($( $("#menu-list").append($(
`<button class="question-menu-item" name="goto-${i}" data-qn="${i}">${i+1}</button>`)); `<button class="question-menu-item" name="goto-${i}" data-qn="${i}">${i+1}</button>`));
+31 -16
View File
@@ -47,7 +47,11 @@ from rest_framework.pagination import PageNumberPagination
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from .forms import CidUserAnswerForm, ExamForm from .forms import CidUserAnswerForm, ExamForm
from .decorators import user_is_author_or_physics_checker, user_is_exam_author_or_physics_checker from .decorators import (
user_is_author_or_physics_checker,
user_is_exam_author_or_physics_checker,
)
class AuthorOrCheckerRequiredMixin(object): class AuthorOrCheckerRequiredMixin(object):
def get_object(self, *args, **kwargs): def get_object(self, *args, **kwargs):
@@ -58,6 +62,7 @@ class AuthorOrCheckerRequiredMixin(object):
raise PermissionDenied() # or Http404 raise PermissionDenied() # or Http404
return obj return obj
def question_list(request): def question_list(request):
questions = Question.objects.all() questions = Question.objects.all()
return render(request, "physics/question_list.html", {"questions": questions}) return render(request, "physics/question_list.html", {"questions": questions})
@@ -196,7 +201,6 @@ def exam_scores_cid_user(request, pk, sk):
answers_marks = [] answers_marks = []
answers = [] answers = []
view_all_results = False view_all_results = False
if request.user.groups.filter(name="view_all_results").exists(): if request.user.groups.filter(name="view_all_results").exists():
view_all_results = True view_all_results = True
@@ -258,6 +262,7 @@ def exam_take_old(request, pk):
}, },
) )
def exam_start(request, pk): def exam_start(request, pk):
exam = get_object_or_404(Exam, pk=pk) exam = get_object_or_404(Exam, pk=pk)
@@ -272,13 +277,13 @@ def exam_start(request, pk):
}, },
) )
def exam_finish(request, pk, cid): def exam_finish(request, pk, cid):
exam = get_object_or_404(Exam, pk=pk) exam = get_object_or_404(Exam, pk=pk)
questions = exam.exam_questions.all() questions = exam.exam_questions.all()
answers = CidUserAnswer.objects.filter( answers = CidUserAnswer.objects.filter(cid=cid, exam=exam)
cid=cid, exam=exam)
answer_question_map = {} answer_question_map = {}
for ans in answers: for ans in answers:
@@ -287,8 +292,8 @@ def exam_finish(request, pk, cid):
question_answer_tuples = [] question_answer_tuples = []
answer_count = 0 answer_count = 0
for q in questions: for q in questions:
#if q in answer_question_map and answer_question_map[q].answer: # if q in answer_question_map and answer_question_map[q].answer:
if q in answer_question_map: # might need to improve this if q in answer_question_map: # might need to improve this
question_answer_tuples.append((q, answer_question_map[q])) question_answer_tuples.append((q, answer_question_map[q]))
answer_count += 1 answer_count += 1
else: else:
@@ -309,6 +314,7 @@ def exam_finish(request, pk, cid):
}, },
) )
def exam_take(request, pk, sk, cid): def exam_take(request, pk, sk, cid):
exam = get_object_or_404(Exam, pk=pk) exam = get_object_or_404(Exam, pk=pk)
@@ -322,15 +328,14 @@ def exam_take(request, pk, sk, cid):
pos = exam.get_question_index(question) pos = exam.get_question_index(question)
answer = question.cid_user_answers.filter( answer = question.cid_user_answers.filter(cid=cid, exam=exam).first()
cid=cid, exam=exam).first()
if request.method == "POST": if request.method == "POST":
if answer: if answer:
form = CidUserAnswerForm(request.POST, instance=answer) form = CidUserAnswerForm(request.POST, instance=answer)
else: else:
form = CidUserAnswerForm(request.POST) form = CidUserAnswerForm(request.POST)
if form.is_valid(): if form.is_valid() and not exam.publish_results:
answer = form.save(commit=False) answer = form.save(commit=False)
answer.cid = cid answer.cid = cid
answer.question = question answer.question = question
@@ -344,7 +349,9 @@ def exam_take(request, pk, sk, cid):
elif "finish" in request.POST: elif "finish" in request.POST:
return redirect("physics:exam_finish", pk=pk, cid=cid) return redirect("physics:exam_finish", pk=pk, cid=cid)
elif "goto" in request.POST: elif "goto" in request.POST:
return redirect("physics:exam_take", pk=pk, sk=int(request.POST.get("goto")), cid=cid) return redirect(
"physics:exam_take", pk=pk, sk=int(request.POST.get("goto")), cid=cid
)
else: else:
form = CidUserAnswerForm(instance=answer) form = CidUserAnswerForm(instance=answer)
@@ -359,7 +366,6 @@ def exam_take(request, pk, sk, cid):
if answer is not None: if answer is not None:
saved_answer = [answer.a, answer.b, answer.c, answer.d, answer.e] saved_answer = [answer.a, answer.b, answer.c, answer.d, answer.e]
return render( return render(
request, request,
"physics/exam_take.html", "physics/exam_take.html",
@@ -372,10 +378,10 @@ def exam_take(request, pk, sk, cid):
"previous": previous, "previous": previous,
"exam_length": exam_length, "exam_length": exam_length,
"pos": pos, "pos": pos,
"saved_answer": saved_answer,
}, },
) )
def loadJsonAnswer(answer): def loadJsonAnswer(answer):
# As access is not restricted make sure the data appears valid # As access is not restricted make sure the data appears valid
if (not isinstance(answer["cid"], int)) or (not isinstance(answer["eid"], int)): if (not isinstance(answer["cid"], int)) or (not isinstance(answer["eid"], int)):
@@ -388,7 +394,7 @@ def loadJsonAnswer(answer):
exam = get_object_or_404(Exam, pk=answer["eid"]) exam = get_object_or_404(Exam, pk=answer["eid"])
#if not exam.active: # if not exam.active:
# return False, JsonResponse( # return False, JsonResponse(
# {"success": False, "error": "No active exam: {}".format(answer["eid"])} # {"success": False, "error": "No active exam: {}".format(answer["eid"])}
# ) # )
@@ -432,10 +438,12 @@ def loadJsonAnswer(answer):
return True, None return True, None
PhysicsExamViews = ExamViews(Exam, Question, "physics", "physics", loadJsonAnswer) PhysicsExamViews = ExamViews(Exam, Question, "physics", "physics", loadJsonAnswer)
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam) GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView): class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
model = Exam model = Exam
form_class = ExamForm form_class = ExamForm
@@ -447,21 +455,28 @@ class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
form.instance.author.add(self.request.user.id) form.instance.author.add(self.request.user.id)
return super().form_valid(form) return super().form_valid(form)
class ExamClone(AuthorOrCheckerRequiredMixin, ExamCloneMixin, ExamCreate): class ExamClone(AuthorOrCheckerRequiredMixin, ExamCloneMixin, ExamCreate):
"""Clone exam view""" """Clone exam view"""
class QuestionView(LoginRequiredMixin, SingleTableMixin, FilterView, AuthorOrCheckerRequiredMixin):
class QuestionView(
LoginRequiredMixin, SingleTableMixin, FilterView, AuthorOrCheckerRequiredMixin
):
model = Question model = Question
table_class = QuestionTable table_class = QuestionTable
template_name = "physics/question_view.html" template_name = "physics/question_view.html"
filterset_class = QuestionFilter filterset_class = QuestionFilter
class UserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView): class UserAnswerView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, DetailView):
model = CidUserAnswer model = CidUserAnswer
class UserAnswerTableView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, SingleTableMixin, FilterView): class UserAnswerTableView(
AuthorOrCheckerRequiredMixin, LoginRequiredMixin, SingleTableMixin, FilterView
):
model = CidUserAnswer model = CidUserAnswer
table_class = UserAnswerTable table_class = UserAnswerTable
template_name = "physics/user_answer_question_view.html" template_name = "physics/user_answer_question_view.html"
@@ -472,4 +487,4 @@ class UserAnswerTableView(AuthorOrCheckerRequiredMixin, LoginRequiredMixin, Sing
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView): class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
model = CidUserAnswer model = CidUserAnswer
template_name = "user_answer_delete.html" template_name = "user_answer_delete.html"
success_url = reverse_lazy("physics:user_answer_table_view") success_url = reverse_lazy("physics:user_answer_table_view")