Merge branch 'master' of ssh://git.xkjq.uk:30001/ross/rad
This commit is contained in:
+10
-10
@@ -238,19 +238,19 @@ def loadJsonAnswer(answer):
|
||||
if (not isinstance(answer["cid"], int)) or (
|
||||
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
|
||||
):
|
||||
return JsonResponse({"success": False, "error": "cid or eid or answers not defined"})
|
||||
return False, JsonResponse({"success": False, "error": "cid or eid or answers not defined"})
|
||||
|
||||
# The model should catch invalid data but this should be less intensive
|
||||
max_int = 999999999999999999999
|
||||
if answer["cid"] > max_int or eid > max_int:
|
||||
return JsonResponse({"success": False, "error": "invalid cid"})
|
||||
return False, JsonResponse({"success": False, "error": "invalid cid"})
|
||||
|
||||
exam = get_object_or_404(Exam, pk=eid)
|
||||
|
||||
if not exam.active:
|
||||
return JsonResponse(
|
||||
{"success": False, "error": "No active exam: {}".format(eid)}
|
||||
)
|
||||
#if not exam.active:
|
||||
# return False, JsonResponse(
|
||||
# {"success": False, "error": "No active exam: {}".format(eid)}
|
||||
# )
|
||||
|
||||
exiting_answers = CidUserAnswer.objects.filter(
|
||||
question__id=answer["qid"], exam__id=eid, cid=answer["cid"]
|
||||
@@ -272,7 +272,7 @@ def loadJsonAnswer(answer):
|
||||
ans.full_clean()
|
||||
ans.save()
|
||||
|
||||
return True
|
||||
return True, None
|
||||
|
||||
|
||||
#@csrf_exempt
|
||||
@@ -453,7 +453,7 @@ def exam_scores_cid(request, pk):
|
||||
questions = exam.exam_questions.all()
|
||||
|
||||
cids = (
|
||||
CidUserAnswer.objects.filter(question__in=questions)
|
||||
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||
.order_by("cid")
|
||||
.values_list("cid", flat=True)
|
||||
.distinct()
|
||||
@@ -473,7 +473,7 @@ def exam_scores_cid(request, pk):
|
||||
user_names[cid] = cid
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
s = q.cid_user_answers.filter(cid=cid).first()
|
||||
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
if not s:
|
||||
# skip if no answer
|
||||
user_answers_marks[cid].append(0)
|
||||
@@ -564,7 +564,7 @@ def exam_scores_cid_user(request, pk, sk):
|
||||
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
user_answer = q.cid_user_answers.filter(cid=cid).first()
|
||||
user_answer = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
if not user_answer:
|
||||
# skip if no answer
|
||||
answers_marks.append(0)
|
||||
|
||||
+19
-8
@@ -157,6 +157,10 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
self.question_type = question_type
|
||||
self.loadJsonAnswer = loadJsonAnswer
|
||||
|
||||
# THis may be better than check_user_access below
|
||||
#group_map = {"rapids" : "rapid_checker", "anatomy" : "anatomy_checker", "longs":"long_checker"}
|
||||
#exam_group = group_map[self.app_name]
|
||||
|
||||
def check_user_access(self, user):
|
||||
"""Check if a user should be able to access a view
|
||||
|
||||
@@ -174,6 +178,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
return False
|
||||
if self.app_name == "physics" and not user.groups.filter(name='physic_checker').exists():
|
||||
return False
|
||||
if self.app_name == "sbas" and not user.groups.filter(name='sba_checker').exists():
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@@ -326,6 +332,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
|
||||
questions = exam.exam_questions.all()
|
||||
|
||||
# TODO: fix showing unmarked answer count from other exams...
|
||||
return render(
|
||||
request, "{}/mark_overview.html".format(self.app_name), {"exam": exam, "questions": questions}
|
||||
)
|
||||
@@ -384,7 +391,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
active_exams = {"exams": []}
|
||||
|
||||
for exam in exams:
|
||||
if exam.active:
|
||||
if exam.active or self.check_user_access(request.user):
|
||||
if exam.json_creation_time:
|
||||
creation_time = exam.json_creation_time.isoformat()
|
||||
else:
|
||||
@@ -401,7 +408,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
"type": self.question_type,
|
||||
"eid": "{}/{}".format(self.question_type, exam.pk),
|
||||
"json_creation_time": creation_time,
|
||||
"exam_json_id": exam.exam_json_id
|
||||
"exam_json_id": exam.exam_json_id,
|
||||
"exam_active": exam.active
|
||||
}
|
||||
|
||||
if self.question_type == "long":
|
||||
@@ -426,13 +434,15 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
n = 0
|
||||
|
||||
for answer in json.loads(request.POST.get("answers")):
|
||||
ret = self.loadJsonAnswer(answer)
|
||||
ret_status, ret = self.loadJsonAnswer(answer)
|
||||
|
||||
#if ret is not True:
|
||||
# return ret
|
||||
|
||||
if ret:
|
||||
if ret_status:
|
||||
n = n + 1
|
||||
else:
|
||||
return ret
|
||||
|
||||
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
||||
# print(request.urlencode())
|
||||
@@ -446,17 +456,18 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
"""
|
||||
exam = get_object_or_404(self.Exam, pk=pk)
|
||||
|
||||
if not exam.active:
|
||||
if not exam.active and not self.check_user_access(request.user):
|
||||
raise Http404("No available exam")
|
||||
|
||||
exam_json = exam.get_exam_json(based=False)
|
||||
#exam_json["exam_active"] = False
|
||||
return JsonResponse(exam_json)
|
||||
|
||||
def exam_json(self, request, pk):
|
||||
|
||||
exam = get_object_or_404(self.Exam, pk=pk)
|
||||
|
||||
if not exam.active:
|
||||
if not exam.active and not self.check_user_access(request.user):
|
||||
raise Http404("No available exam")
|
||||
|
||||
|
||||
@@ -504,7 +515,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
question = get_object_or_404(self.Question, pk=sk)
|
||||
exam = get_object_or_404(self.Exam, pk=pk)
|
||||
|
||||
if not exam.active:
|
||||
if not exam.active and not self.check_user_access(request.user):
|
||||
raise Http404("No available exam")
|
||||
|
||||
|
||||
@@ -520,7 +531,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
question = get_object_or_404(self.Question, pk=sk)
|
||||
exam = get_object_or_404(self.Exam, pk=pk)
|
||||
|
||||
if not exam.active:
|
||||
if not exam.active and not self.check_user_access(request.user):
|
||||
raise Http404("No available exam")
|
||||
|
||||
return redirect("{}:question_json_unbased".format(self.app_name), pk=sk)
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
<br />
|
||||
{% for series in question.series.all %}
|
||||
<div class="series-block">
|
||||
Series {{forloop.counter0 }}:<br />
|
||||
Series {{forloop.counter }}:<br />
|
||||
{{series.get_block}}
|
||||
</div>
|
||||
{% empty %}
|
||||
No series
|
||||
{% endfor %}
|
||||
<div>
|
||||
Author(s): {{question.get_authors}}
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
<button type="submit" name="next" class="save btn btn-default" title="Save answer and move to next question">Next answer</button>
|
||||
<!-- <button type="submit" name="skip" class="save btn btn-default">Skip</button> -->
|
||||
{% else %}
|
||||
(no more answers for this question to mark)
|
||||
{% if not unmarked %}
|
||||
All question answers marker. <a href="{% url 'longs:mark_overview' pk=exam.pk %}">Return to marking overview</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+14
-12
@@ -571,21 +571,21 @@ def loadJsonAnswer(answer):
|
||||
if (not isinstance(answer["cid"], int)) or (
|
||||
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
|
||||
):
|
||||
return JsonResponse(
|
||||
return False, JsonResponse(
|
||||
{"success": False, "error": "cid or eid or answers not defined"}
|
||||
)
|
||||
|
||||
# The model should catch invalid data but this should be less intensive
|
||||
max_int = 999999999999999999999
|
||||
if answer["cid"] > max_int or eid > max_int:
|
||||
return JsonResponse({"success": False, "error": "invalid cid"})
|
||||
return False, JsonResponse({"success": False, "error": "invalid cid"})
|
||||
|
||||
exam = get_object_or_404(Exam, pk=eid)
|
||||
|
||||
if not exam.active:
|
||||
return JsonResponse(
|
||||
{"success": False, "error": "No active exam: {}".format(eid)}
|
||||
)
|
||||
#if not exam.active:
|
||||
# return False, JsonResponse(
|
||||
# {"success": False, "error": "No active exam: {}".format(eid)}
|
||||
# )
|
||||
|
||||
exiting_answers = CidUserAnswer.objects.filter(
|
||||
question__id=answer["qid"], exam__id=eid, cid=answer["cid"]
|
||||
@@ -627,7 +627,7 @@ def loadJsonAnswer(answer):
|
||||
ans.full_clean()
|
||||
ans.save()
|
||||
|
||||
return True
|
||||
return True, None
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -650,7 +650,7 @@ def mark_answer(request, pk, sk, tk):
|
||||
raise Http404("Exam question does not exist")
|
||||
|
||||
try:
|
||||
answer = question.cid_user_answers.get(cid=tk)
|
||||
answer = question.cid_user_answers.get(cid=tk, exam__id=pk)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404("User answer does not exist")
|
||||
|
||||
@@ -678,6 +678,8 @@ def mark_answer(request, pk, sk, tk):
|
||||
|
||||
if "next" in request.POST:
|
||||
return redirect("longs:mark_answer", pk=pk, sk=sk, tk=next_unmarked_id)
|
||||
if "save" in request.POST:
|
||||
return redirect("longs:mark_answer", pk=pk, sk=sk, tk=tk)
|
||||
#elif "previous" in request.POST:
|
||||
# return redirect("longs:mark", pk=pk, sk=n - 1)
|
||||
|
||||
@@ -720,7 +722,7 @@ def mark(request, pk, sk):
|
||||
raise Http404("Exam question does not exist")
|
||||
|
||||
|
||||
user_answers = question.cid_user_answers.all()
|
||||
user_answers = question.cid_user_answers.filter(exam__id=pk)
|
||||
|
||||
return render(
|
||||
request,
|
||||
@@ -742,7 +744,7 @@ def exam_scores_cid(request, pk):
|
||||
questions = exam.exam_questions.all()
|
||||
|
||||
cids = (
|
||||
CidUserAnswer.objects.filter(question__in=questions)
|
||||
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||
.order_by("cid")
|
||||
.values_list("cid", flat=True)
|
||||
.distinct()
|
||||
@@ -762,7 +764,7 @@ def exam_scores_cid(request, pk):
|
||||
user_names[cid] = cid
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
s = q.cid_user_answers.filter(cid=cid).first()
|
||||
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
|
||||
if not s:
|
||||
# skip if no answer, (score 4)
|
||||
@@ -855,7 +857,7 @@ def exam_scores_cid_user(request, pk, sk):
|
||||
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
user_answer = q.cid_user_answers.filter(cid=cid).first()
|
||||
user_answer = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
|
||||
|
||||
|
||||
|
||||
+7
-7
@@ -245,19 +245,19 @@ def exam_take(request, pk):
|
||||
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 JsonResponse({"success": False, "error": "invalid"})
|
||||
return False, JsonResponse({"success": False, "error": "invalid"})
|
||||
|
||||
# The model should catch invalid data but this should be less intensive
|
||||
max_int = 10000000
|
||||
if answer["cid"] > max_int or answer["eid"] > max_int:
|
||||
return JsonResponse({"success": False})
|
||||
return False, JsonResponse({"success": False})
|
||||
|
||||
exam = get_object_or_404(Exam, pk=answer["eid"])
|
||||
|
||||
if not exam.active:
|
||||
return JsonResponse(
|
||||
{"success": False, "error": "No active exam: {}".format(answer["eid"])}
|
||||
)
|
||||
#if not exam.active:
|
||||
# return False, JsonResponse(
|
||||
# {"success": False, "error": "No active exam: {}".format(answer["eid"])}
|
||||
# )
|
||||
|
||||
questions = defaultdict(dict)
|
||||
|
||||
@@ -296,6 +296,6 @@ def loadJsonAnswer(answer):
|
||||
ans.full_clean()
|
||||
ans.save()
|
||||
|
||||
return True
|
||||
return True, None
|
||||
|
||||
PhysicsExamViews = ExamViews(Exam, Question, "physics", "physics", loadJsonAnswer)
|
||||
@@ -131,6 +131,11 @@ def active_exams(request):
|
||||
|
||||
active_exams = {"exams": exams}
|
||||
|
||||
if request.user:
|
||||
active_exams["user"] = request.user.username
|
||||
else:
|
||||
active_exams["user"] = False
|
||||
|
||||
return JsonResponse(active_exams)
|
||||
|
||||
def active_exams_unbased(request):
|
||||
|
||||
+10
-10
@@ -580,21 +580,21 @@ def loadJsonAnswer(answer):
|
||||
if (not isinstance(answer["cid"], int)) or (
|
||||
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
|
||||
):
|
||||
return JsonResponse(
|
||||
return False, JsonResponse(
|
||||
{"success": False, "error": "cid or eid or answers not defined"}
|
||||
)
|
||||
|
||||
# The model should catch invalid data but this should be less intensive
|
||||
max_int = 999999999999999999999
|
||||
if answer["cid"] > max_int or eid > max_int:
|
||||
return JsonResponse({"success": False, "error": "invalid cid"})
|
||||
return False, JsonResponse({"success": False, "error": "invalid cid"})
|
||||
|
||||
exam = get_object_or_404(Exam, pk=eid)
|
||||
|
||||
if not exam.active:
|
||||
return JsonResponse(
|
||||
{"success": False, "error": "No active exam: {}".format(eid)}
|
||||
)
|
||||
#if not exam.active:
|
||||
# return False, JsonResponse(
|
||||
# {"success": False, "error": "No active exam: {}".format(eid)}
|
||||
# )
|
||||
|
||||
exiting_answers = CidUserAnswer.objects.filter(
|
||||
question__id=answer["qid"], exam__id=eid, cid=answer["cid"]
|
||||
@@ -631,7 +631,7 @@ def loadJsonAnswer(answer):
|
||||
ans.full_clean()
|
||||
ans.save()
|
||||
|
||||
return True
|
||||
return True, None
|
||||
|
||||
|
||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
||||
@@ -787,7 +787,7 @@ def exam_scores_cid(request, pk):
|
||||
questions = exam.exam_questions.all()
|
||||
|
||||
cids = (
|
||||
CidUserAnswer.objects.filter(question__in=questions)
|
||||
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||
.order_by("cid")
|
||||
.values_list("cid", flat=True)
|
||||
.distinct()
|
||||
@@ -807,7 +807,7 @@ def exam_scores_cid(request, pk):
|
||||
user_names[cid] = cid
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
s = q.cid_user_answers.filter(cid=cid).first()
|
||||
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
|
||||
if not s:
|
||||
# skip if no answer
|
||||
@@ -901,7 +901,7 @@ def exam_scores_cid_user(request, pk, sk):
|
||||
|
||||
for q in questions:
|
||||
# Get user answer
|
||||
user_answer = q.cid_user_answers.filter(cid=cid).first()
|
||||
user_answer = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||
|
||||
if not user_answer or user_answer is None:
|
||||
# skip if no answer
|
||||
|
||||
@@ -16,4 +16,5 @@
|
||||
{% if request.user.is_staff %}<a href="{% url 'admin:index'%}">Admin</a>{% endif %}
|
||||
</div>
|
||||
<p>A radiology resource</p>
|
||||
<p><a href="http://www.penracourses.org.uk/rts">RTS is available here</a></p>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user