.
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from sortedm2m.fields import SortedManyToManyField
|
from sortedm2m.fields import SortedManyToManyField
|
||||||
|
|
||||||
|
|||||||
+1
-77
@@ -221,82 +221,6 @@ def answer_question(request, pk):
|
|||||||
# return JsonResponse(data)
|
# return JsonResponse(data)
|
||||||
|
|
||||||
|
|
||||||
def loadJsonAnswer(answer):
|
|
||||||
# Backend eid is just the object pk number
|
|
||||||
# in the frontend this is appended with the type
|
|
||||||
# e.g. anatomy/1
|
|
||||||
|
|
||||||
# TODO Update to only allow valid Candidates
|
|
||||||
eid = int(answer["eid"].split("/")[1])
|
|
||||||
cid = int(answer["cid"])
|
|
||||||
# As access is not restricted make sure the data appears valid
|
|
||||||
if (not isinstance(cid, int)) or (
|
|
||||||
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
|
|
||||||
):
|
|
||||||
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 cid > max_int or eid > max_int:
|
|
||||||
return False, JsonResponse({"success": False, "error": "invalid cid"})
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=eid)
|
|
||||||
|
|
||||||
|
|
||||||
if not exam.check_cid_user(cid, answer["passcode"]):
|
|
||||||
return False, JsonResponse(
|
|
||||||
{"success": False, "error": "invalid cid / passcode"}
|
|
||||||
)
|
|
||||||
|
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
|
||||||
question__id=answer["qid"], exam__id=eid, cid=cid
|
|
||||||
)
|
|
||||||
|
|
||||||
if not exiting_answers:
|
|
||||||
ans = CidUserAnswer(answer=answer["ans"], cid=cid)
|
|
||||||
ans.question_id = answer["qid"]
|
|
||||||
ans.exam_id = eid
|
|
||||||
ans.score = Answer.MarkOptions.UNMARKED
|
|
||||||
|
|
||||||
ans.full_clean()
|
|
||||||
|
|
||||||
ans.save()
|
|
||||||
else:
|
|
||||||
# Update an existing answer
|
|
||||||
# should never be more than one (famous last words)
|
|
||||||
ans = exiting_answers[0]
|
|
||||||
ans.answer = answer["ans"]
|
|
||||||
ans.score = Answer.MarkOptions.UNMARKED
|
|
||||||
ans.full_clean()
|
|
||||||
ans.save()
|
|
||||||
|
|
||||||
return True, None
|
|
||||||
|
|
||||||
|
|
||||||
# @csrf_exempt
|
|
||||||
# def postExamAnswers(request):
|
|
||||||
# if request.is_ajax and request.method == "POST":
|
|
||||||
#
|
|
||||||
# n = 0
|
|
||||||
# # horrible but it works
|
|
||||||
# #for k in request.POST.dict():
|
|
||||||
#
|
|
||||||
# for answer in json.loads(request.POST.get("answers")):
|
|
||||||
# ret = loadJsonAnswer(answer)
|
|
||||||
#
|
|
||||||
# if ret is not True:
|
|
||||||
# return ret
|
|
||||||
# n = n + 1
|
|
||||||
#
|
|
||||||
# # print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
|
||||||
# # print(request.urlencode())
|
|
||||||
#
|
|
||||||
# return JsonResponse({"success": True, "question_count": n})
|
|
||||||
# return JsonResponse({"success": False, "error": "Invalid data"})
|
|
||||||
#
|
|
||||||
# # return render(request, "anatomy/exam.html", {"exam" : exam, "question" : question})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -1006,7 +930,7 @@ def question_save_annotation(request, pk):
|
|||||||
|
|
||||||
|
|
||||||
GenericExamViews = ExamViews(
|
GenericExamViews = ExamViews(
|
||||||
Exam, AnatomyQuestion, Answer, CidUserAnswer, "anatomy", "anatomy", loadJsonAnswer
|
Exam, AnatomyQuestion, Answer, CidUserAnswer, "anatomy", "anatomy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.html import mark_safe
|
from django.utils.html import mark_safe
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|||||||
+1
-1
@@ -1556,5 +1556,5 @@ def collection_scores_cid(request, pk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
GenericExamViews = ExamViews(
|
GenericExamViews = ExamViews(
|
||||||
CaseCollection, Case, None, CidReportAnswer, "atlas", "casecollection", None
|
CaseCollection, Case, None, CidReportAnswer, "atlas", "casecollection"
|
||||||
)
|
)
|
||||||
+95
-11
@@ -271,7 +271,6 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
cid_user_answer,
|
cid_user_answer,
|
||||||
app,
|
app,
|
||||||
question_type,
|
question_type,
|
||||||
loadJsonAnswer,
|
|
||||||
):
|
):
|
||||||
self.Exam = exam
|
self.Exam = exam
|
||||||
self.Question = question
|
self.Question = question
|
||||||
@@ -279,7 +278,6 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
self.CidUserAnswer = cid_user_answer
|
self.CidUserAnswer = cid_user_answer
|
||||||
self.app_name = app
|
self.app_name = app
|
||||||
self.question_type = question_type
|
self.question_type = question_type
|
||||||
self.loadJsonAnswer = loadJsonAnswer
|
|
||||||
|
|
||||||
# THis may be better than check_user_access below
|
# THis may be better than check_user_access below
|
||||||
# group_map = {"rapids" : "rapid_checker", "anatomy" : "anatomy_checker", "longs":"long_checker"}
|
# group_map = {"rapids" : "rapid_checker", "anatomy" : "anatomy_checker", "longs":"long_checker"}
|
||||||
@@ -1069,21 +1067,107 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
{"success": False, "error": "cid or eid or answers not defined"}
|
{"success": False, "error": "cid or eid or answers not defined"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
exam = get_object_or_404(self.Exam, pk=eid)
|
||||||
|
|
||||||
|
if not exam.check_cid_user(cid, answer["passcode"], user_id=uid):
|
||||||
|
return JsonResponse(
|
||||||
|
{"success": False, "error": "invalid cid / passcode"}
|
||||||
|
)
|
||||||
|
|
||||||
|
if uid:
|
||||||
|
existing_answers = self.CidUserAnswer.objects.filter(
|
||||||
|
question__id=answer["qid"], exam__id=eid, user__id=uid
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
existing_answers = self.CidUserAnswer.objects.filter(
|
||||||
|
question__id=answer["qid"], exam__id=eid, cid=cid
|
||||||
|
)
|
||||||
|
posted_answer = answer["ans"]
|
||||||
|
|
||||||
|
match self.app_name:
|
||||||
|
case "rapids":
|
||||||
|
|
||||||
|
# Normal answers are just posted with the answer "Normal"
|
||||||
|
normal = False
|
||||||
|
if posted_answer == "Normal":
|
||||||
|
normal = True
|
||||||
|
|
||||||
|
if not existing_answers:
|
||||||
|
if uid:
|
||||||
|
ans = self.CidUserAnswer(answer=posted_answer, normal=normal, user=User.objects.get(id=uid))
|
||||||
|
else:
|
||||||
|
ans = self.CidUserAnswer(answer=posted_answer, normal=normal, cid=cid)
|
||||||
|
|
||||||
|
ans.question_id = answer["qid"]
|
||||||
|
ans.exam_id = eid
|
||||||
|
else:
|
||||||
|
# Update an existing answer
|
||||||
|
# should never be more than one (famous last words)
|
||||||
|
ans = existing_answers[0]
|
||||||
|
if answer["qidn"] == "1":
|
||||||
|
ans.normal = normal
|
||||||
|
ans.answer = ""
|
||||||
|
elif answer["qidn"] == "2" and not ans.normal:
|
||||||
|
ans.answer = posted_answer
|
||||||
|
case "anatomy":
|
||||||
|
if not existing_answers:
|
||||||
|
if uid:
|
||||||
|
ans = self.CidUserAnswer(answer=posted_answer, uid=User.objects.get(id=uid))
|
||||||
|
else:
|
||||||
|
ans = self.CidUserAnswer(answer=posted_answer, cid=cid)
|
||||||
|
|
||||||
|
|
||||||
|
ans.question_id = answer["qid"]
|
||||||
|
ans.exam_id = eid
|
||||||
|
ans.score = self.Answer.MarkOptions.UNMARKED
|
||||||
|
else:
|
||||||
|
# Update an existing answer
|
||||||
|
# should never be more than one (famous last words)
|
||||||
|
ans = existing_answers[0]
|
||||||
|
ans.answer = posted_answer
|
||||||
|
ans.score = self.Answer.MarkOptions.UNMARKED
|
||||||
|
case "longs":
|
||||||
|
# Long cases seperate sections by qidn
|
||||||
|
qidn = answer["qidn"]
|
||||||
|
|
||||||
|
# If the user answer does not exist
|
||||||
|
if not existing_answers:
|
||||||
|
if uid:
|
||||||
|
ans = self.CidUserAnswer(user=User.objects.get(id=uid))
|
||||||
|
else:
|
||||||
|
ans = self.CidUserAnswer(cid=cid)
|
||||||
|
ans.question_id = answer["qid"]
|
||||||
|
ans.exam_id = eid
|
||||||
|
|
||||||
|
# If the answer already exists or we have started populating it
|
||||||
|
else:
|
||||||
|
# Update an existing answer
|
||||||
|
# should never be more than one (famous last words)
|
||||||
|
ans = existing_answers[0]
|
||||||
|
|
||||||
|
if qidn == "1":
|
||||||
|
ans.answer_observations = posted_answer
|
||||||
|
elif qidn == "2":
|
||||||
|
ans.answer_interpretation = posted_answer
|
||||||
|
elif qidn == "3":
|
||||||
|
ans.answer_principle_diagnosis = posted_answer
|
||||||
|
elif qidn == "4":
|
||||||
|
ans.answer_differential_diagnosis = posted_answer
|
||||||
|
elif qidn == "5":
|
||||||
|
ans.answer_management = posted_answer
|
||||||
|
|
||||||
|
# Mark as unmarked
|
||||||
|
ans.score = ans.ScoreOptions.UNMARKED
|
||||||
|
|
||||||
|
ans.full_clean()
|
||||||
|
ans.save()
|
||||||
|
|
||||||
|
|
||||||
ret_status, ret = self.loadJsonAnswer(answer, cid=cid, eid=eid, uid=uid)
|
|
||||||
# try:
|
|
||||||
# ret_status, ret = self.loadJsonAnswer(answer)
|
|
||||||
# except:
|
|
||||||
# # We catch the error here so users get an error (rather than 500)
|
|
||||||
# return JsonResponse({"success": False, "error": "Invalid data"})
|
|
||||||
|
|
||||||
# if ret is not True:
|
# if ret is not True:
|
||||||
# return ret
|
# return ret
|
||||||
|
|
||||||
if ret_status:
|
|
||||||
n = n + 1
|
n = n + 1
|
||||||
else:
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
||||||
# print(request.urlencode())
|
# print(request.urlencode())
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.html import mark_safe
|
from django.utils.html import mark_safe
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|||||||
+1
-70
@@ -615,75 +615,6 @@ class LongSeriesView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = LongSeriesFilter
|
filterset_class = LongSeriesFilter
|
||||||
|
|
||||||
|
|
||||||
def loadJsonAnswer(answer):
|
|
||||||
eid = int(answer["eid"].split("/")[1])
|
|
||||||
cid = int(answer["cid"])
|
|
||||||
|
|
||||||
# As access is not restricted make sure the data appears valid
|
|
||||||
if (not isinstance(cid, int)) or (
|
|
||||||
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
|
|
||||||
):
|
|
||||||
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 cid > max_int or eid > max_int:
|
|
||||||
return False, JsonResponse({"success": False, "error": "invalid cid"})
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=eid)
|
|
||||||
|
|
||||||
if not exam.check_cid_user(cid, answer["passcode"]):
|
|
||||||
return False, JsonResponse(
|
|
||||||
{"success": False, "error": "invalid cid / passcode"}
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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=cid
|
|
||||||
)
|
|
||||||
|
|
||||||
posted_answer = answer["ans"]
|
|
||||||
|
|
||||||
# Long cases seperate sections by qidn
|
|
||||||
qidn = answer["qidn"]
|
|
||||||
|
|
||||||
# If the user answer does not exist
|
|
||||||
if not exiting_answers:
|
|
||||||
ans = CidUserAnswer(cid=cid)
|
|
||||||
ans.question_id = answer["qid"]
|
|
||||||
ans.exam_id = eid
|
|
||||||
|
|
||||||
# If the answer already exists or we have started populating it
|
|
||||||
else:
|
|
||||||
# Update an existing answer
|
|
||||||
# should never be more than one (famous last words)
|
|
||||||
ans = exiting_answers[0]
|
|
||||||
|
|
||||||
if qidn == "1":
|
|
||||||
ans.answer_observations = posted_answer
|
|
||||||
elif qidn == "2":
|
|
||||||
ans.answer_interpretation = posted_answer
|
|
||||||
elif qidn == "3":
|
|
||||||
ans.answer_principle_diagnosis = posted_answer
|
|
||||||
elif qidn == "4":
|
|
||||||
ans.answer_differential_diagnosis = posted_answer
|
|
||||||
elif qidn == "5":
|
|
||||||
ans.answer_management = posted_answer
|
|
||||||
|
|
||||||
# Mark as unmarked
|
|
||||||
ans.score = ans.ScoreOptions.UNMARKED
|
|
||||||
|
|
||||||
ans.full_clean()
|
|
||||||
ans.save()
|
|
||||||
|
|
||||||
return True, None
|
|
||||||
|
|
||||||
|
|
||||||
@user_is_long_marker
|
@user_is_long_marker
|
||||||
@reversion.create_revision()
|
@reversion.create_revision()
|
||||||
@@ -1178,7 +1109,7 @@ def long_series_order_upload_filename(request, pk):
|
|||||||
return redirect("longs:long_series_detail", pk=pk)
|
return redirect("longs:long_series_detail", pk=pk)
|
||||||
|
|
||||||
|
|
||||||
GenericExamViews = ExamViews(Exam, Long, None, CidUserAnswer, "longs", "long", loadJsonAnswer)
|
GenericExamViews = ExamViews(Exam, Long, None, CidUserAnswer, "longs", "long")
|
||||||
|
|
||||||
|
|
||||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from sortedm2m.fields import SortedManyToManyField
|
from sortedm2m.fields import SortedManyToManyField
|
||||||
|
|
||||||
|
|||||||
+55
-55
@@ -311,65 +311,65 @@ 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
|
# # 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)):
|
||||||
return False, JsonResponse({"success": False, "error": "invalid"})
|
# return False, JsonResponse({"success": False, "error": "invalid"})
|
||||||
|
#
|
||||||
# The model should catch invalid data but this should be less intensive
|
# # The model should catch invalid data but this should be less intensive
|
||||||
max_int = 2147483647
|
# max_int = 2147483647
|
||||||
if answer["cid"] > max_int or answer["eid"] > max_int:
|
# if answer["cid"] > max_int or answer["eid"] > max_int:
|
||||||
return False, JsonResponse({"success": False, "error": "invalid candidate id"})
|
# return False, JsonResponse({"success": False, "error": "invalid candidate id"})
|
||||||
|
#
|
||||||
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"])}
|
||||||
|
# # )
|
||||||
|
#
|
||||||
|
# questions = defaultdict(dict)
|
||||||
|
#
|
||||||
|
# for q, n, a in answer["ans"]:
|
||||||
|
# questions[q][n] = a
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
# for qid in questions:
|
||||||
|
# exiting_answers = CidUserAnswer.objects.filter(
|
||||||
|
# question__id=qid, exam__id=answer["eid"], cid=answer["cid"]
|
||||||
# )
|
# )
|
||||||
|
#
|
||||||
questions = defaultdict(dict)
|
# a = questions[qid]["a"]
|
||||||
|
# b = questions[qid]["b"]
|
||||||
for q, n, a in answer["ans"]:
|
# c = questions[qid]["c"]
|
||||||
questions[q][n] = a
|
# d = questions[qid]["d"]
|
||||||
pass
|
# e = questions[qid]["e"]
|
||||||
|
#
|
||||||
for qid in questions:
|
# if not exiting_answers:
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
# ans = CidUserAnswer(a=a, b=b, c=c, d=d, e=e, cid=answer["cid"])
|
||||||
question__id=qid, exam__id=answer["eid"], cid=answer["cid"]
|
# ans.question_id = qid
|
||||||
)
|
# ans.exam_id = answer["eid"]
|
||||||
|
#
|
||||||
a = questions[qid]["a"]
|
# ans.full_clean()
|
||||||
b = questions[qid]["b"]
|
#
|
||||||
c = questions[qid]["c"]
|
# ans.save()
|
||||||
d = questions[qid]["d"]
|
# else:
|
||||||
e = questions[qid]["e"]
|
# # Update an existing answer
|
||||||
|
# # should never be more than one (famous last words)
|
||||||
if not exiting_answers:
|
# ans = exiting_answers[0]
|
||||||
ans = CidUserAnswer(a=a, b=b, c=c, d=d, e=e, cid=answer["cid"])
|
# ans.a = a
|
||||||
ans.question_id = qid
|
# ans.b = b
|
||||||
ans.exam_id = answer["eid"]
|
# ans.c = c
|
||||||
|
# ans.d = d
|
||||||
ans.full_clean()
|
# ans.e = e
|
||||||
|
# ans.full_clean()
|
||||||
ans.save()
|
# ans.save()
|
||||||
else:
|
#
|
||||||
# Update an existing answer
|
# return True, None
|
||||||
# should never be more than one (famous last words)
|
|
||||||
ans = exiting_answers[0]
|
|
||||||
ans.a = a
|
|
||||||
ans.b = b
|
|
||||||
ans.c = c
|
|
||||||
ans.d = d
|
|
||||||
ans.e = e
|
|
||||||
ans.full_clean()
|
|
||||||
ans.save()
|
|
||||||
|
|
||||||
return True, None
|
|
||||||
|
|
||||||
|
|
||||||
GenericExamViews = ExamViews(
|
GenericExamViews = ExamViews(
|
||||||
Exam, Question, None, CidUserAnswer, "physics", "physics", loadJsonAnswer
|
Exam, Question, None, CidUserAnswer, "physics", "physics"
|
||||||
)
|
)
|
||||||
|
|
||||||
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.html import mark_safe
|
from django.utils.html import mark_safe
|
||||||
|
|
||||||
from sortedm2m.fields import SortedManyToManyField
|
from sortedm2m.fields import SortedManyToManyField
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
import pytest
|
import pytest
|
||||||
from rapids.models import Abnormality, Exam
|
from rapids.models import Abnormality, Exam
|
||||||
|
from rapids.views import GenericExamViews
|
||||||
|
|
||||||
#@pytest.mark.django_db
|
#@pytest.mark.django_db
|
||||||
def test_create_abnormality(db):
|
def test_create_abnormality(db):
|
||||||
abnormality = Abnormality.objects.create(name="Abnorm")
|
abnormality = Abnormality.objects.create(name="Abnorm")
|
||||||
assert abnormality.name == "Abnorm"
|
assert abnormality.name == "Abnorm"
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def create_basic_user(db, django_user_model):
|
||||||
|
return django_user_model.objects.create_superuser("basicuser", "ross@xkjq.uk", "password")
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def create_exam(db):
|
def create_exam(db):
|
||||||
return Exam.objects.create(name="test exam")
|
return Exam.objects.create(name="test exam", exam_mode=True)
|
||||||
|
|
||||||
def test_exam_creation(create_exam):
|
def test_exam_creation(create_exam):
|
||||||
exams = Exam.objects.filter(name="test exam")
|
exams = Exam.objects.filter(name="test exam")
|
||||||
@@ -18,3 +24,27 @@ def test_exam_creation(create_exam):
|
|||||||
exam = exams.first()
|
exam = exams.first()
|
||||||
|
|
||||||
assert exam.time_limit == 35 * 60
|
assert exam.time_limit == 35 * 60
|
||||||
|
|
||||||
|
def test_exam_list(rf, admin_user, create_exam):
|
||||||
|
request = rf.get('/rapids/exam/')
|
||||||
|
# Remember that when using RequestFactory, the request does not pass
|
||||||
|
# through middleware. If your view expects fields such as request.user
|
||||||
|
# to be set, you need to set them explicitly.
|
||||||
|
# The following line sets request.user to an admin user.
|
||||||
|
request.user = admin_user
|
||||||
|
response = GenericExamViews.exam_list(request)
|
||||||
|
#print(response)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_exam_active_admin(rf, admin_user, create_exam, client):
|
||||||
|
request = rf.get(reverse('rapids:active_exams'))
|
||||||
|
request.user = admin_user
|
||||||
|
response = GenericExamViews.active_exams(request)
|
||||||
|
print(response.content)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_exam_active_basic_user(create_basic_user, create_exam, client):
|
||||||
|
client.login(username="basicuser", password="password")
|
||||||
|
response = client.get(reverse('rapids:active_exams'))
|
||||||
|
print(response.content)
|
||||||
|
assert response.status_code == 200
|
||||||
+1
-56
@@ -509,61 +509,6 @@ class RapidView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = RapidFilter
|
filterset_class = RapidFilter
|
||||||
|
|
||||||
|
|
||||||
def loadJsonAnswer(answer, cid, eid, uid):
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=eid)
|
|
||||||
|
|
||||||
if not exam.check_cid_user(cid, answer["passcode"], user_id=uid):
|
|
||||||
return False, JsonResponse(
|
|
||||||
{"success": False, "error": "invalid cid / passcode"}
|
|
||||||
)
|
|
||||||
|
|
||||||
if uid:
|
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
|
||||||
question__id=answer["qid"], exam__id=eid, user__id=uid
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
|
||||||
question__id=answer["qid"], exam__id=eid, cid=cid
|
|
||||||
)
|
|
||||||
|
|
||||||
posted_answer = answer["ans"]
|
|
||||||
|
|
||||||
## qidn 1 does not hold answer data (but should always arrive prior to 2)
|
|
||||||
# if answer["qidn"] == "1":
|
|
||||||
# posted_answer = ""
|
|
||||||
|
|
||||||
# Normal answers are just posted with the answer "Normal"
|
|
||||||
normal = False
|
|
||||||
if posted_answer == "Normal":
|
|
||||||
normal = True
|
|
||||||
|
|
||||||
if not exiting_answers:
|
|
||||||
if uid:
|
|
||||||
ans = CidUserAnswer(answer=posted_answer, normal=normal, user=User.objects.get(id=uid))
|
|
||||||
else:
|
|
||||||
ans = CidUserAnswer(answer=posted_answer, normal=normal, cid=cid)
|
|
||||||
|
|
||||||
ans.question_id = answer["qid"]
|
|
||||||
ans.exam_id = eid
|
|
||||||
|
|
||||||
ans.full_clean()
|
|
||||||
|
|
||||||
ans.save()
|
|
||||||
else:
|
|
||||||
# Update an existing answer
|
|
||||||
# should never be more than one (famous last words)
|
|
||||||
ans = exiting_answers[0]
|
|
||||||
if answer["qidn"] == "1":
|
|
||||||
ans.normal = normal
|
|
||||||
ans.answer = ""
|
|
||||||
elif answer["qidn"] == "2" and not ans.normal:
|
|
||||||
ans.answer = posted_answer
|
|
||||||
ans.full_clean()
|
|
||||||
ans.save()
|
|
||||||
|
|
||||||
return True, None
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def mark_all(request, exam_pk, sk):
|
def mark_all(request, exam_pk, sk):
|
||||||
@@ -818,7 +763,7 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
|||||||
|
|
||||||
|
|
||||||
GenericExamViews = ExamViews(
|
GenericExamViews = ExamViews(
|
||||||
Exam, Rapid, Answer, CidUserAnswer, "rapids", "rapid", loadJsonAnswer
|
Exam, Rapid, Answer, CidUserAnswer, "rapids", "rapid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ from django.utils.html import format_html
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from sortedm2m.fields import SortedManyToManyField
|
from sortedm2m.fields import SortedManyToManyField
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -285,12 +285,8 @@ def exam_take(request, pk, sk, cid, passcode):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def loadJsonAnswer(answer):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
GenericExamViews = ExamViews(
|
GenericExamViews = ExamViews(
|
||||||
Exam, Question, None, CidUserAnswer, "sbas", "sbas", loadJsonAnswer
|
Exam, Question, None, CidUserAnswer, "sbas", "sbas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user