from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required, user_passes_test from django.views.decorators.csrf import csrf_exempt from django.http import Http404, JsonResponse from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth.mixins import LoginRequiredMixin from django.utils.decorators import method_decorator from django.core.cache import cache import json from django.views import View from .forms import ( ExaminationForm, ) from .models import Examination from rapids.models import Rapid as RapidQuestion from rapids.models import Exam as RapidExam from longs.models import Long as LongQuestion from longs.models import Exam as LongExam from anatomy.models import AnatomyQuestion as AnatomyQuestion from anatomy.models import Exam as AnatomyExam from django.db.models import Case, When # Create your views here. @login_required def create_examination(request): form = ExaminationForm(request.POST or None) if form.is_valid(): instance = form.save() return HttpResponse( '' % (instance.pk, instance) ) return render( request, "rapids/create_simple.html", {"form": form, "name": "Examination"} ) @csrf_exempt def get_examination_id(request): if request.is_ajax(): examination_name = request.GET["examination_name"] examination_id = Examination.objects.get(name=examination_name).id data = { "examination_id": examination_id, } return HttpResponse(json.dumps(data), content_type="application/json") return HttpResponse("/") # Generic view to dispatch to indivuals app views @login_required def generic_exam_json_edit(request): if request.is_ajax() and request.method == "POST": question_type = request.POST.get("type") if question_type == "rapid": Exam = RapidExam Question = RapidQuestion elif question_type == "long": Exam = LongExam Question = LongQuestion elif question_type == "anatomy": Exam = AnatomyExam Question = AnatomyQuestion else: data = {"status": "error"} return JsonResponse(data, status=400) exam = get_object_or_404(Exam, pk=request.POST.get("exam_id")) if "add_exam_questions" in request.POST: question_ids = json.loads(request.POST.get("add_exam_questions")) question_objects = Question.objects.filter(pk__in=question_ids) for i in question_ids: exam.exam_questions.add(i) #exam.exam_questions.add(question_objects) exam.save() data = {"status": "success"} return JsonResponse(data, status=200) if "set_open_access" in request.POST: if request.POST.get("set_open_access") == "true": state = True else: state = False questions_changed = [] for q in exam.exam_questions.all(): q.open_access = state q.save() questions_changed.append(q.pk) data = {"status": "success", "questions": questions_changed, "state": state} return JsonResponse(data, status=200) if "set_exam_order" in request.POST: new_order = json.loads(request.POST.get("set_exam_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) if len(objects) != exam.exam_questions.count(): data = {"status": "error, count does not match"} return JsonResponse(data, status=400) exam.exam_questions.set(objects) exam.save() data = {"status": "success"} return JsonResponse(data, status=200) data = {"status": "error, unknown request"} return JsonResponse(data, status=400) else: data = {"status": "error"} return JsonResponse(data, status=400) class ExamViews(View, LoginRequiredMixin): def __init__(self, exam, question, app, question_type, loadJsonAnswer): self.Exam = exam self.Question = question self.app_name = app self.question_type = question_type self.loadJsonAnswer = loadJsonAnswer @method_decorator(login_required) def exam_toggle_results_published(self, request, pk): if request.is_ajax() and request.method == "POST": exam = get_object_or_404(self.Exam, pk=pk) exam.publish_results = ( True if request.POST.get("publish_results") == "true" else False ) exam.save() data = {"status": "success", "publish_results": exam.publish_results} return JsonResponse(data, status=200) else: data = {"status": "error"} return JsonResponse(data, status=400) @method_decorator(login_required) def exam_toggle_active(self, request, pk): if request.is_ajax() and request.method == "POST": exam = get_object_or_404(self.Exam, pk=pk) exam.active = True if request.POST.get("active") == "true" else False exam.save() data = {"status": "success", "active": exam.active} return JsonResponse(data, status=200) else: data = {"status": "error"} return JsonResponse(data, status=400) @method_decorator(login_required) def exam_json_recreate(self, request, pk): exam = get_object_or_404(self.Exam, pk=pk) exam.recreate_json = True exam.save() return redirect("{}:exam_overview".format(self.app_name), pk=pk) @method_decorator(login_required) def exam_list(self, request): exams = self.Exam.objects.all() return render(request, "{}/exam_list.html".format(self.app_name), {"exams": exams}) @method_decorator(login_required) def exam_overview(self, request, pk): #print(Exam.objects.all()) #exams = Exam.objects.all() #print("test", Exam.objects.all().get(id=pk)) exam = get_object_or_404(self.Exam, pk=pk) questions = exam.exam_questions.all() question_number = len(questions) return render( request, "{}/exam_overview.html".format(self.app_name), {"exam": exam, "questions": questions, "question_number": question_number}, ) @method_decorator(login_required) def exam_json_edit(self, request, pk): if request.is_ajax() and request.method == "POST": exam = get_object_or_404(self.Exam, pk=pk) if "add_exam_questions" in request.POST: question_ids = json.loads(request.POST.get("add_exam_questions")) question_objects = self.Question.objects.filter(pk__in=question_ids) exam.exam_questions.add(question_objects) exam.save() data = {"status": "success"} return JsonResponse(data, status=200) if "set_open_access" in request.POST: if request.POST.get("set_open_access") == "true": state = True else: state = False questions_changed = [] for q in exam.exam_questions.all(): q.open_access = state q.save() questions_changed.append(q.pk) data = {"status": "success", "questions": questions_changed, "state": state} return JsonResponse(data, status=200) if "set_exam_order" in request.POST: new_order = json.loads(request.POST.get("set_exam_order")) preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(new_order)]) objects = self.Question.objects.filter(pk__in=new_order).order_by(preserved) if len(objects) != exam.exam_questions.count(): data = {"status": "error, count does not match"} return JsonResponse(data, status=400) exam.exam_questions.set(objects) exam.save() data = {"status": "success"} return JsonResponse(data, status=200) data = {"status": "error, unknown request"} return JsonResponse(data, status=400) else: data = {"status": "error"} return JsonResponse(data, status=400) @method_decorator(login_required) def mark_overview(self, request, pk): exam = get_object_or_404(self.Exam, pk=pk) questions = exam.exam_questions.all() return render( request, "{}/mark_overview.html".format(self.app_name), {"exam": exam, "questions": questions} ) @method_decorator(login_required) def index(self, request): exams = self.Exam.objects.all() return render(request, "{}/index.html".format(self.app_name), {"exams": exams}) @method_decorator(login_required) def exam_question_detail(self, request, pk, sk): exam = get_object_or_404(self.Exam, pk=pk) question = exam.exam_questions.all()[sk] exam_length = len(exam.exam_questions.all()) pos = exam.get_question_index(question) + 1 previous = -1 if sk > 0: previous = sk - 1 next = sk + 1 if sk == exam_length - 1: next = False return render( request, "{}/question_detail.html".format(self.app_name), { "question": question, "exam": exam, "next": next, "previous": previous, "exam_length": exam_length, "pos": pos, }, ) def active_exams(self, request, json=True): exams = self.Exam.objects.all() active_exams = {"exams": []} for exam in exams: if exam.active: active_exams["exams"].append( { "name": exam.get_exam_name(), "url": request.build_absolute_uri(exam.get_json_url()), "type": self.question_type, } ) if json == False: return active_exams["exams"] return JsonResponse(active_exams) @method_decorator(csrf_exempt) def postExamAnswers(self, request): if request.is_ajax and request.method == "POST": n = 0 for answer in json.loads(request.POST.get("answers")): ret = self.loadJsonAnswer(answer) #if ret is not True: # return ret if 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"}) def exam_json(self, request, pk): exam = get_object_or_404(self.Exam, pk=pk) if not exam.active: raise Http404("No available exam") exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk)) if exam_json_cache is not None and not exam.recreate_json: exam_json_cache["cached"] = True return JsonResponse(exam_json_cache) exam_json = exam.get_exam_json() exam.recreate_json = False exam.save() cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600) return JsonResponse(exam_json)