.
This commit is contained in:
+170
-86
@@ -54,7 +54,8 @@ import os
|
|||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
|
|
||||||
#from rad.views import get_question_and_content_type
|
# from rad.views import get_question_and_content_type
|
||||||
|
|
||||||
|
|
||||||
def get_question_and_content_type(question_type):
|
def get_question_and_content_type(question_type):
|
||||||
if question_type == "rapid":
|
if question_type == "rapid":
|
||||||
@@ -77,6 +78,7 @@ def get_question_and_content_type(question_type):
|
|||||||
|
|
||||||
return question, content_type
|
return question, content_type
|
||||||
|
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
@login_required
|
@login_required
|
||||||
def create_examination(request):
|
def create_examination(request):
|
||||||
@@ -91,6 +93,7 @@ def create_examination(request):
|
|||||||
request, "rapids/create_simple.html", {"form": form, "name": "Examination"}
|
request, "rapids/create_simple.html", {"form": form, "name": "Examination"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def get_examination_id(request):
|
def get_examination_id(request):
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
@@ -102,6 +105,7 @@ def get_examination_id(request):
|
|||||||
return HttpResponse(json.dumps(data), content_type="application/json")
|
return HttpResponse(json.dumps(data), content_type="application/json")
|
||||||
return HttpResponse("/")
|
return HttpResponse("/")
|
||||||
|
|
||||||
|
|
||||||
# Generic view to dispatch to indivuals app views
|
# Generic view to dispatch to indivuals app views
|
||||||
@login_required
|
@login_required
|
||||||
def generic_exam_json_edit(request):
|
def generic_exam_json_edit(request):
|
||||||
@@ -127,10 +131,9 @@ def generic_exam_json_edit(request):
|
|||||||
data = {"status": "error"}
|
data = {"status": "error"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=request.POST.get("exam_id"))
|
exam = get_object_or_404(Exam, pk=request.POST.get("exam_id"))
|
||||||
|
|
||||||
#if "exam_toggle_active" in request.POST:
|
# if "exam_toggle_active" in request.POST:
|
||||||
# active = json.loads(request.POST.get("active"))
|
# active = json.loads(request.POST.get("active"))
|
||||||
|
|
||||||
# data = {"status": "success"}
|
# data = {"status": "success"}
|
||||||
@@ -138,7 +141,7 @@ def generic_exam_json_edit(request):
|
|||||||
|
|
||||||
if "add_exam_questions" in request.POST:
|
if "add_exam_questions" in request.POST:
|
||||||
question_ids = json.loads(request.POST.get("add_exam_questions"))
|
question_ids = json.loads(request.POST.get("add_exam_questions"))
|
||||||
#question_objects = Question.objects.filter(pk__in=question_ids)
|
# question_objects = Question.objects.filter(pk__in=question_ids)
|
||||||
|
|
||||||
add_count = 0
|
add_count = 0
|
||||||
for i in question_ids:
|
for i in question_ids:
|
||||||
@@ -148,13 +151,15 @@ def generic_exam_json_edit(request):
|
|||||||
exam.exam_questions.add(i)
|
exam.exam_questions.add(i)
|
||||||
|
|
||||||
exam.save()
|
exam.save()
|
||||||
data = {"status": "success", "questions added" : add_count}
|
data = {"status": "success", "questions added": add_count}
|
||||||
return JsonResponse(data, status=200)
|
return JsonResponse(data, status=200)
|
||||||
|
|
||||||
if "set_exam_order" in request.POST:
|
if "set_exam_order" in request.POST:
|
||||||
new_order = json.loads(request.POST.get("set_exam_order"))
|
new_order = json.loads(request.POST.get("set_exam_order"))
|
||||||
|
|
||||||
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(new_order)])
|
preserved = Case(
|
||||||
|
*[When(pk=pk, then=pos) for pos, pk in enumerate(new_order)]
|
||||||
|
)
|
||||||
objects = Question.objects.filter(pk__in=new_order).order_by(preserved)
|
objects = Question.objects.filter(pk__in=new_order).order_by(preserved)
|
||||||
|
|
||||||
if len(objects) != exam.exam_questions.count():
|
if len(objects) != exam.exam_questions.count():
|
||||||
@@ -167,13 +172,22 @@ def generic_exam_json_edit(request):
|
|||||||
return JsonResponse(data, status=200)
|
return JsonResponse(data, status=200)
|
||||||
|
|
||||||
# Only checkers can do the following
|
# Only checkers can do the following
|
||||||
if question_type == "rapid" and not request.user.groups.filter(name='rapid_checker').exists():
|
if (
|
||||||
|
question_type == "rapid"
|
||||||
|
and not request.user.groups.filter(name="rapid_checker").exists()
|
||||||
|
):
|
||||||
data = {"status": "error, permission denied"}
|
data = {"status": "error, permission denied"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
if question_type == "anatomy" and not request.user.groups.filter(name='anatomy_checker').exists():
|
if (
|
||||||
|
question_type == "anatomy"
|
||||||
|
and not request.user.groups.filter(name="anatomy_checker").exists()
|
||||||
|
):
|
||||||
data = {"status": "error, permission denied"}
|
data = {"status": "error, permission denied"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
if question_type == "long" and not request.user.groups.filter(name='long_checker').exists():
|
if (
|
||||||
|
question_type == "long"
|
||||||
|
and not request.user.groups.filter(name="long_checker").exists()
|
||||||
|
):
|
||||||
data = {"status": "error, permission denied"}
|
data = {"status": "error, permission denied"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
@@ -192,8 +206,6 @@ def generic_exam_json_edit(request):
|
|||||||
data = {"status": "success", "questions": questions_changed, "state": state}
|
data = {"status": "success", "questions": questions_changed, "state": state}
|
||||||
return JsonResponse(data, status=200)
|
return JsonResponse(data, status=200)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data = {"status": "error, unknown request"}
|
data = {"status": "error, unknown request"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
else:
|
else:
|
||||||
@@ -201,7 +213,6 @@ def generic_exam_json_edit(request):
|
|||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ExamViews(View, LoginRequiredMixin):
|
class ExamViews(View, LoginRequiredMixin):
|
||||||
def __init__(self, exam, question, app, question_type, loadJsonAnswer):
|
def __init__(self, exam, question, app, question_type, loadJsonAnswer):
|
||||||
self.Exam = exam
|
self.Exam = exam
|
||||||
@@ -211,8 +222,8 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
self.loadJsonAnswer = loadJsonAnswer
|
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"}
|
||||||
#exam_group = group_map[self.app_name]
|
# exam_group = group_map[self.app_name]
|
||||||
|
|
||||||
def check_user_access(self, user, exam_id=None):
|
def check_user_access(self, user, exam_id=None):
|
||||||
"""Check if a user should be able to access a view
|
"""Check if a user should be able to access a view
|
||||||
@@ -228,15 +239,32 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if exam.open_access or user in exam.get_author_objects():
|
if exam.open_access or user in exam.get_author_objects():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.app_name == "rapids" and not user.groups.filter(name='rapid_checker').exists():
|
if (
|
||||||
|
self.app_name == "rapids"
|
||||||
|
and not user.groups.filter(name="rapid_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "anatomy" and not user.groups.filter(name='anatomy_checker').exists():
|
if (
|
||||||
|
self.app_name == "anatomy"
|
||||||
|
and not user.groups.filter(name="anatomy_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "longs" and not user.groups.filter(name__in=('long_checker', 'long_marker')).exists():
|
if (
|
||||||
|
self.app_name == "longs"
|
||||||
|
and not user.groups.filter(
|
||||||
|
name__in=("long_checker", "long_marker")
|
||||||
|
).exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "physics" and not user.groups.filter(name='physics_checker').exists():
|
if (
|
||||||
|
self.app_name == "physics"
|
||||||
|
and not user.groups.filter(name="physics_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "sbas" and not user.groups.filter(name='sba_checker').exists():
|
if (
|
||||||
|
self.app_name == "sbas"
|
||||||
|
and not user.groups.filter(name="sba_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -255,20 +283,33 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if exam.open_access or user in exam.get_author_objects():
|
if exam.open_access or user in exam.get_author_objects():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.app_name == "rapids" and not user.groups.filter(name='rapid_checker').exists():
|
if (
|
||||||
|
self.app_name == "rapids"
|
||||||
|
and not user.groups.filter(name="rapid_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "anatomy" and not user.groups.filter(name='anatomy_checker').exists():
|
if (
|
||||||
|
self.app_name == "anatomy"
|
||||||
|
and not user.groups.filter(name="anatomy_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "longs" and not user.groups.filter(name__in=('long_checker')).exists():
|
if (
|
||||||
|
self.app_name == "longs"
|
||||||
|
and not user.groups.filter(name__in=("long_checker")).exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "physics" and not user.groups.filter(name='physics_checker').exists():
|
if (
|
||||||
|
self.app_name == "physics"
|
||||||
|
and not user.groups.filter(name="physics_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self.app_name == "sbas" and not user.groups.filter(name='sba_checker').exists():
|
if (
|
||||||
|
self.app_name == "sbas"
|
||||||
|
and not user.groups.filter(name="sba_checker").exists()
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def exam_toggle_results_published(self, request, pk):
|
def exam_toggle_results_published(self, request, pk):
|
||||||
if request.is_ajax() and request.method == "POST":
|
if request.is_ajax() and request.method == "POST":
|
||||||
@@ -285,7 +326,6 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
data = {"status": "error"}
|
data = {"status": "error"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def exam_toggle_active(self, request, pk):
|
def exam_toggle_active(self, request, pk):
|
||||||
if request.is_ajax() and request.method == "POST":
|
if request.is_ajax() and request.method == "POST":
|
||||||
@@ -329,26 +369,31 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if all:
|
if all:
|
||||||
exams = self.Exam.objects.all().order_by("name")
|
exams = self.Exam.objects.all().order_by("name")
|
||||||
else:
|
else:
|
||||||
exams = self.Exam.objects.filter(exam_mode=True, archive=False).order_by("name")
|
exams = self.Exam.objects.filter(exam_mode=True, archive=False).order_by(
|
||||||
|
"name"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.check_user_access(request.user):
|
if not self.check_user_access(request.user):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
return render(request, "{}/exam_list.html".format(self.app_name), {"exams": exams})
|
return render(
|
||||||
|
request, "{}/exam_list.html".format(self.app_name), {"exams": exams}
|
||||||
|
)
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def exam_overview(self, request, pk):
|
def exam_overview(self, request, pk):
|
||||||
#print(Exam.objects.all())
|
# print(Exam.objects.all())
|
||||||
#exams = Exam.objects.all()
|
# exams = Exam.objects.all()
|
||||||
#print("test", Exam.objects.all().get(id=pk))
|
# print("test", Exam.objects.all().get(id=pk))
|
||||||
exam = get_object_or_404(self.Exam, pk=pk)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
if request.user not in exam.author.all():
|
if request.user not in exam.author.all():
|
||||||
if not self.check_user_access(request.user, pk):
|
if not self.check_user_access(request.user, pk):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
can_edit = self.check_user_edit_access(request.user, pk) | request.user.is_superuser
|
can_edit = (
|
||||||
|
self.check_user_edit_access(request.user, pk) | request.user.is_superuser
|
||||||
|
)
|
||||||
|
|
||||||
notes = []
|
notes = []
|
||||||
if can_edit:
|
if can_edit:
|
||||||
@@ -361,10 +406,16 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"{}/exam_overview.html".format(self.app_name),
|
"{}/exam_overview.html".format(self.app_name),
|
||||||
{"exam": exam, "questions": questions, "question_number": question_number, "can_edit": can_edit, "notes": notes},
|
{
|
||||||
|
"exam": exam,
|
||||||
|
"questions": questions,
|
||||||
|
"question_number": question_number,
|
||||||
|
"can_edit": can_edit,
|
||||||
|
"notes": notes,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
#@method_decorator(login_required)
|
# @method_decorator(login_required)
|
||||||
def exam_notes(self, request, pk):
|
def exam_notes(self, request, pk):
|
||||||
exam = get_object_or_404(self.Exam, pk=pk)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
@@ -377,11 +428,12 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
question_pks = exam.exam_questions.values_list("pk", flat=True)
|
question_pks = exam.exam_questions.values_list("pk", flat=True)
|
||||||
|
|
||||||
# Get active notes for type
|
# Get active notes for type
|
||||||
notes = QuestionNote.objects.filter(content_type=content_type, object_id__in=question_pks, complete=False)
|
notes = QuestionNote.objects.filter(
|
||||||
|
content_type=content_type, object_id__in=question_pks, complete=False
|
||||||
|
)
|
||||||
|
|
||||||
return notes
|
return notes
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def exam_json_edit(self, request, pk):
|
def exam_json_edit(self, request, pk):
|
||||||
if request.is_ajax() and request.method == "POST":
|
if request.is_ajax() and request.method == "POST":
|
||||||
@@ -404,11 +456,15 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if "set_exam_order" in request.POST:
|
if "set_exam_order" in request.POST:
|
||||||
new_order = json.loads(request.POST.get("set_exam_order"))
|
new_order = json.loads(request.POST.get("set_exam_order"))
|
||||||
|
|
||||||
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(new_order)])
|
preserved = Case(
|
||||||
objects = self.Question.objects.filter(pk__in=new_order).order_by(preserved)
|
*[When(pk=pk, then=pos) for pos, pk in enumerate(new_order)]
|
||||||
|
)
|
||||||
|
objects = self.Question.objects.filter(pk__in=new_order).order_by(
|
||||||
|
preserved
|
||||||
|
)
|
||||||
|
|
||||||
# We now allow deleting exam questions
|
# We now allow deleting exam questions
|
||||||
#if len(objects) != exam.exam_questions.count():
|
# if len(objects) != exam.exam_questions.count():
|
||||||
# data = {"status": "error, count does not match"}
|
# data = {"status": "error, count does not match"}
|
||||||
# return JsonResponse(data, status=400)
|
# return JsonResponse(data, status=400)
|
||||||
|
|
||||||
@@ -417,7 +473,6 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
data = {"status": "success"}
|
data = {"status": "success"}
|
||||||
return JsonResponse(data, status=200)
|
return JsonResponse(data, status=200)
|
||||||
|
|
||||||
|
|
||||||
if not self.check_user_access(request.user, pk):
|
if not self.check_user_access(request.user, pk):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
@@ -433,7 +488,11 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
q.save()
|
q.save()
|
||||||
questions_changed.append(q.pk)
|
questions_changed.append(q.pk)
|
||||||
|
|
||||||
data = {"status": "success", "questions": questions_changed, "state": state}
|
data = {
|
||||||
|
"status": "success",
|
||||||
|
"questions": questions_changed,
|
||||||
|
"state": state,
|
||||||
|
}
|
||||||
return JsonResponse(data, status=200)
|
return JsonResponse(data, status=200)
|
||||||
|
|
||||||
data = {"status": "error, unknown request"}
|
data = {"status": "error, unknown request"}
|
||||||
@@ -453,40 +512,63 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not self.check_user_access(request.user, pk):
|
if not self.check_user_access(request.user, pk):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
|
|
||||||
# Handle exams that require double marking
|
# Handle exams that require double marking
|
||||||
try:
|
try:
|
||||||
if exam.double_mark:
|
if exam.double_mark:
|
||||||
question_unmarked_map = []
|
question_unmarked_map = []
|
||||||
for q in questions:
|
for q in questions:
|
||||||
question_unmarked_map.append((q, int(q.get_unmarked_user_answer_count(exam_pk=exam.pk)), int(q.get_unmarked_user_answer_count(exam_pk=exam.pk, marker=request.user)) ))
|
question_unmarked_map.append(
|
||||||
|
(
|
||||||
|
q,
|
||||||
|
int(q.get_unmarked_user_answer_count(exam_pk=exam.pk)),
|
||||||
|
int(
|
||||||
|
q.get_unmarked_user_answer_count(
|
||||||
|
exam_pk=exam.pk, marker=request.user
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request, "{}/mark_overview.html".format(self.app_name), {"exam": exam, "question_unmarked_map": question_unmarked_map}
|
request,
|
||||||
|
"{}/mark_overview.html".format(self.app_name),
|
||||||
|
{"exam": exam, "question_unmarked_map": question_unmarked_map},
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
question_unmarked_map = []
|
question_unmarked_map = []
|
||||||
for q in questions:
|
for q in questions:
|
||||||
question_unmarked_map.append((q, int(q.get_unmarked_user_answer_count(exam_pk=exam.pk))))
|
question_unmarked_map.append(
|
||||||
|
(q, int(q.get_unmarked_user_answer_count(exam_pk=exam.pk)))
|
||||||
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request, "{}/mark_overview.html".format(self.app_name), {"exam": exam, "question_unmarked_map": question_unmarked_map}
|
request,
|
||||||
|
"{}/mark_overview.html".format(self.app_name),
|
||||||
|
{"exam": exam, "question_unmarked_map": question_unmarked_map},
|
||||||
)
|
)
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def index(self, request):
|
def index(self, request):
|
||||||
exams = self.Exam.objects.filter(author__id=request.user.id)
|
exams = self.Exam.objects.filter(author__id=request.user.id)
|
||||||
|
|
||||||
if self.app_name == "rapids" and request.user.groups.filter(name='rapid_checker').exists():
|
if (
|
||||||
|
self.app_name == "rapids"
|
||||||
|
and request.user.groups.filter(name="rapid_checker").exists()
|
||||||
|
):
|
||||||
exams = self.Exam.objects.all()
|
exams = self.Exam.objects.all()
|
||||||
if self.app_name == "anatomy" and request.user.groups.filter(name='anatomy_checker').exists():
|
if (
|
||||||
|
self.app_name == "anatomy"
|
||||||
|
and request.user.groups.filter(name="anatomy_checker").exists()
|
||||||
|
):
|
||||||
exams = self.Exam.objects.all()
|
exams = self.Exam.objects.all()
|
||||||
if self.app_name == "longs" and request.user.groups.filter(name='long_checker').exists():
|
if (
|
||||||
|
self.app_name == "longs"
|
||||||
|
and request.user.groups.filter(name="long_checker").exists()
|
||||||
|
):
|
||||||
exams = self.Exam.objects.all()
|
exams = self.Exam.objects.all()
|
||||||
|
|
||||||
return render(request, "{}/index.html".format(self.app_name), {"exams": exams})
|
return render(request, "{}/index.html".format(self.app_name), {"exams": exams})
|
||||||
@@ -499,7 +581,6 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not self.check_user_access(request.user, pk):
|
if not self.check_user_access(request.user, pk):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
|
|
||||||
question = exam.exam_questions.all()[sk]
|
question = exam.exam_questions.all()[sk]
|
||||||
|
|
||||||
exam_length = len(exam.exam_questions.all())
|
exam_length = len(exam.exam_questions.all())
|
||||||
@@ -550,7 +631,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
"eid": "{}/{}".format(self.question_type, exam.pk),
|
"eid": "{}/{}".format(self.question_type, exam.pk),
|
||||||
"json_creation_time": creation_time,
|
"json_creation_time": creation_time,
|
||||||
"exam_json_id": exam.exam_json_id,
|
"exam_json_id": exam.exam_json_id,
|
||||||
"exam_active": exam.active
|
"exam_active": exam.active,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.question_type == "long":
|
if self.question_type == "long":
|
||||||
@@ -561,7 +642,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
question.get_question_json()
|
question.get_question_json()
|
||||||
h[question.pk] = question.question_json_id
|
h[question.pk] = question.question_json_id
|
||||||
obj["multi_question_json"] = h
|
obj["multi_question_json"] = h
|
||||||
active_exams["exams"].append( obj )
|
active_exams["exams"].append(obj)
|
||||||
|
|
||||||
if json == False:
|
if json == False:
|
||||||
return active_exams["exams"]
|
return active_exams["exams"]
|
||||||
@@ -581,8 +662,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
# We catch the error here so users get an error (rather than 500)
|
# We catch the error here so users get an error (rather than 500)
|
||||||
return JsonResponse({"success": False, "error": "Invalid data"})
|
return JsonResponse({"success": False, "error": "Invalid data"})
|
||||||
|
|
||||||
|
# if ret is not True:
|
||||||
#if ret is not True:
|
|
||||||
# return ret
|
# return ret
|
||||||
|
|
||||||
if ret_status:
|
if ret_status:
|
||||||
@@ -606,7 +686,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
|
|
||||||
exam_json = exam.get_exam_json(based=False)
|
exam_json = exam.get_exam_json(based=False)
|
||||||
#exam_json["exam_active"] = False
|
# exam_json["exam_active"] = False
|
||||||
return JsonResponse(exam_json)
|
return JsonResponse(exam_json)
|
||||||
|
|
||||||
def exam_json(self, request, pk):
|
def exam_json(self, request, pk):
|
||||||
@@ -616,18 +696,17 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not exam.active and not self.check_user_access(request.user, pk):
|
if not exam.active and not self.check_user_access(request.user, pk):
|
||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
|
|
||||||
|
# exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk))
|
||||||
|
|
||||||
#exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk))
|
path = "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk)
|
||||||
|
url = "{0}{1}/exam/{2}.json".format(settings.MEDIA_URL, self.app_name, pk)
|
||||||
path= "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk)
|
|
||||||
url= "{0}{1}/exam/{2}.json".format(settings.MEDIA_URL, self.app_name, pk)
|
|
||||||
|
|
||||||
if os.path.isfile(path) and not exam.recreate_json:
|
if os.path.isfile(path) and not exam.recreate_json:
|
||||||
#exam_json_cache["cached"] = True
|
# exam_json_cache["cached"] = True
|
||||||
# Make sure we pass on an argument if we are forcing a reload
|
# Make sure we pass on an argument if we are forcing a reload
|
||||||
if request.GET.get('_'):
|
if request.GET.get("_"):
|
||||||
query_string = urllib.parse.urlencode({'_': request.GET.get('_')})
|
query_string = urllib.parse.urlencode({"_": request.GET.get("_")})
|
||||||
url = '{}?{}'.format(url, query_string)
|
url = "{}?{}".format(url, query_string)
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
return JsonResponse(exam_json_cache)
|
return JsonResponse(exam_json_cache)
|
||||||
@@ -649,11 +728,11 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
|
|
||||||
# We also try to clear the cache of any associated questions (longs)
|
# We also try to clear the cache of any associated questions (longs)
|
||||||
# see exam_question_json
|
# see exam_question_json
|
||||||
#n = exam.exam_questions.count()
|
# n = exam.exam_questions.count()
|
||||||
#question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)]
|
# question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)]
|
||||||
#cache.delete_many(question_keys)
|
# cache.delete_many(question_keys)
|
||||||
|
|
||||||
#cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600)
|
# cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600)
|
||||||
|
|
||||||
return JsonResponse(exam_json)
|
return JsonResponse(exam_json)
|
||||||
|
|
||||||
@@ -664,11 +743,10 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not exam.active and not self.check_user_access(request.user, pk):
|
if not exam.active and not self.check_user_access(request.user, pk):
|
||||||
raise Http404("No available exam")
|
raise Http404("No available exam")
|
||||||
|
|
||||||
|
if request.GET.get("_"):
|
||||||
if request.GET.get('_'):
|
|
||||||
base_url = redirect("{}:question_json".format(self.app_name), pk=sk)
|
base_url = redirect("{}:question_json".format(self.app_name), pk=sk)
|
||||||
query_string = urllib.parse.urlencode({'_': request.GET.get('_')})
|
query_string = urllib.parse.urlencode({"_": request.GET.get("_")})
|
||||||
url = '{}?{}'.format(base_url, query_string)
|
url = "{}?{}".format(base_url, query_string)
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
|
|
||||||
return redirect("{}:question_json".format(self.app_name), pk=sk)
|
return redirect("{}:question_json".format(self.app_name), pk=sk)
|
||||||
@@ -704,11 +782,11 @@ class GenericViewBase:
|
|||||||
self.app_name = app_name
|
self.app_name = app_name
|
||||||
|
|
||||||
g = {
|
g = {
|
||||||
"rapids" : "rapid_checker",
|
"rapids": "rapid_checker",
|
||||||
"anatomy" : "anatomy_checker",
|
"anatomy": "anatomy_checker",
|
||||||
"longs" : "longs_checker",
|
"longs": "longs_checker",
|
||||||
"sbas" : "sbas_checker",
|
"sbas": "sbas_checker",
|
||||||
"physics" : "physics_checker",
|
"physics": "physics_checker",
|
||||||
}
|
}
|
||||||
|
|
||||||
self.checker_group = g[app_name]
|
self.checker_group = g[app_name]
|
||||||
@@ -793,18 +871,21 @@ class GenericViewBase:
|
|||||||
questions = self.question_object.objects.filter(author=pk)
|
questions = self.question_object.objects.filter(author=pk)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request, f"{self.app_name}/category_detail.html", {"category": author, "questions": questions}
|
request,
|
||||||
|
f"{self.app_name}/category_detail.html",
|
||||||
|
{"category": author, "questions": questions},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def author_list(self, request):
|
def author_list(self, request):
|
||||||
authors = User.objects.all()
|
authors = User.objects.all()
|
||||||
|
|
||||||
return render(request, f"{self.app_name}/author_list.html", {"authors": authors})
|
return render(
|
||||||
|
request, f"{self.app_name}/author_list.html", {"authors": authors}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExamCloneMixin():
|
class ExamCloneMixin:
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
old_object = get_object_or_404(self.model, pk=self.kwargs["exam_id"])
|
old_object = get_object_or_404(self.model, pk=self.kwargs["exam_id"])
|
||||||
initial_data = model_to_dict(old_object, exclude=["id"])
|
initial_data = model_to_dict(old_object, exclude=["id"])
|
||||||
@@ -849,19 +930,22 @@ class CidUserView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
#user = self.request.user
|
# user = self.request.user
|
||||||
|
|
||||||
physics_exams = [(i.name, i.pk) for i in PhysicsExam.objects.filter(archived=False)]
|
physics_exams = [
|
||||||
|
(i.name, i.pk) for i in PhysicsExam.objects.filter(archive=False)
|
||||||
|
]
|
||||||
|
|
||||||
context["physics_exams"] = physics_exams
|
context["physics_exams"] = physics_exams
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def create_cid_users(request):
|
def create_cid_users(request):
|
||||||
if request.is_ajax() and request.method == "POST":
|
if request.is_ajax() and request.method == "POST":
|
||||||
number = int(request.POST.get("number"))
|
number = int(request.POST.get("number"))
|
||||||
|
|
||||||
new_cid = max(CidUser.objects.all().order_by("-cid")[0].cid+1, 50000)
|
new_cid = max(CidUser.objects.all().order_by("-cid")[0].cid + 1, 50000)
|
||||||
|
|
||||||
for n in range(number):
|
for n in range(number):
|
||||||
passcode = "".join(random.choices(string.ascii_uppercase, k=4))
|
passcode = "".join(random.choices(string.ascii_uppercase, k=4))
|
||||||
|
|||||||
Reference in New Issue
Block a user