continue unifying views
This commit is contained in:
@@ -15,6 +15,9 @@ import string
|
|||||||
|
|
||||||
from generic.models import Examination, ExamBase
|
from generic.models import Examination, ExamBase
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from helpers.images import image_as_base64
|
||||||
|
|
||||||
image_storage = FileSystemStorage(
|
image_storage = FileSystemStorage(
|
||||||
# Physical file location ROOT
|
# Physical file location ROOT
|
||||||
location=u"{0}/anatomy/".format(settings.MEDIA_ROOT),
|
location=u"{0}/anatomy/".format(settings.MEDIA_ROOT),
|
||||||
@@ -273,6 +276,38 @@ class Exam(ExamBase):
|
|||||||
help_text="Exam time limit (in seconds)", default=5400
|
help_text="Exam time limit (in seconds)", default=5400
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_exam_json(self):
|
||||||
|
questions = self.exam_questions.all()
|
||||||
|
|
||||||
|
exam_questions = defaultdict(dict)
|
||||||
|
|
||||||
|
exam_order = []
|
||||||
|
|
||||||
|
for q in questions:
|
||||||
|
exam_order.append(q.id)
|
||||||
|
|
||||||
|
exam_questions[q.id] = {
|
||||||
|
"title": "{}".format(q.description),
|
||||||
|
"question": str(q.question_type),
|
||||||
|
"images": [image_as_base64(q.image)],
|
||||||
|
"annotations": [str(q.image_annotations)],
|
||||||
|
"type": "anatomy",
|
||||||
|
}
|
||||||
|
|
||||||
|
exam_json = {
|
||||||
|
"eid": "anatomy/{}".format(self.id),
|
||||||
|
"cached": False,
|
||||||
|
"exam_type": "anatomy",
|
||||||
|
"exam_name": self.name,
|
||||||
|
"exam_mode": True,
|
||||||
|
"exam_order": exam_order,
|
||||||
|
"questions": exam_questions,
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.time_limit:
|
||||||
|
exam_json["exam_time"] = self.time_limit
|
||||||
|
|
||||||
|
return exam_json
|
||||||
|
|
||||||
|
|
||||||
# class UserAnswer(models.Model):
|
# class UserAnswer(models.Model):
|
||||||
|
|||||||
+6
-6
@@ -5,7 +5,7 @@ app_name = "anatomy"
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('', views.question_list, name='question_list'),
|
# path('', views.question_list, name='question_list'),
|
||||||
path("", views.index, name="index"),
|
path("", views.AnatomyExamViews.index, name="index"),
|
||||||
path("question/", views.AnatomyQuestionView.as_view(), name="anatomy_question_view"),
|
path("question/", views.AnatomyQuestionView.as_view(), name="anatomy_question_view"),
|
||||||
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
||||||
path("question/create/", views.AnatomyQuestionCreate.as_view(), name="anatomy_question_create"),
|
path("question/create/", views.AnatomyQuestionCreate.as_view(), name="anatomy_question_create"),
|
||||||
@@ -16,21 +16,21 @@ urlpatterns = [
|
|||||||
name="answer_question"),
|
name="answer_question"),
|
||||||
path("question/<int:pk>/clone", views.QuestionClone.as_view(), name="question_clone"),
|
path("question/<int:pk>/clone", views.QuestionClone.as_view(), name="question_clone"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.AnatomyExamViews.mark_overview, name="mark_overview"),
|
||||||
path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
path("exam/<int:pk>/question/<int:sk>/", views.exam_question_detail, name="exam_question_detail"),
|
path("exam/<int:pk>/question/<int:sk>/", views.AnatomyExamViews.exam_question_detail, name="exam_question_detail"),
|
||||||
path("exam/<int:pk>/", views.AnatomyExamViews.exam_overview, name="exam_overview"),
|
path("exam/<int:pk>/", views.AnatomyExamViews.exam_overview, name="exam_overview"),
|
||||||
path("exam/<int:pk>/json_edit", views.exam_json_edit, name="exam_json_edit"),
|
path("exam/<int:pk>/json_edit", views.AnatomyExamViews.exam_json_edit, name="exam_json_edit"),
|
||||||
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
||||||
name="exam_scores_cid"),
|
name="exam_scores_cid"),
|
||||||
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
||||||
name="exam_scores_cid_user"),
|
name="exam_scores_cid_user"),
|
||||||
path("exam/<int:pk>/toggle_active", views.AnatomyExamViews.exam_toggle_active, name="exam_toggle_active"),
|
path("exam/<int:pk>/toggle_active", views.AnatomyExamViews.exam_toggle_active, name="exam_toggle_active"),
|
||||||
path("exam/<int:pk>/toggle_results_published", views.AnatomyExamViews.exam_toggle_results_published, name="exam_toggle_results_published"),
|
path("exam/<int:pk>/toggle_results_published", views.AnatomyExamViews.exam_toggle_results_published, name="exam_toggle_results_published"),
|
||||||
path("exam/submit", views.postExamAnswers, name="exam_answers_submit"),
|
path("exam/submit", views.AnatomyExamViews.postExamAnswers, name="exam_answers_submit"),
|
||||||
path("exam/", views.AnatomyExamViews.exam_list, name="exam_list"),
|
path("exam/", views.AnatomyExamViews.exam_list, name="exam_list"),
|
||||||
path("exam/json/", views.AnatomyExamViews.active_exams, name="active_exams"),
|
path("exam/json/", views.AnatomyExamViews.active_exams, name="active_exams"),
|
||||||
path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
path("exam/json/<int:pk>", views.AnatomyExamViews.exam_json, name="exam_json"),
|
||||||
path("exam/json/<int:pk>/recreate", views.AnatomyExamViews.exam_json_recreate, name="exam_json_recreate"),
|
path("exam/json/<int:pk>/recreate", views.AnatomyExamViews.exam_json_recreate, name="exam_json_recreate"),
|
||||||
#path("cid/<int:pk>", views.cid_scores, name="cid_scores"),
|
#path("cid/<int:pk>", views.cid_scores, name="cid_scores"),
|
||||||
#path("cid/", views.cid_selector, name="cid_selector"),
|
#path("cid/", views.cid_selector, name="cid_selector"),
|
||||||
|
|||||||
+25
-205
@@ -75,17 +75,12 @@ def user_is_admin(user):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def question_list(request):
|
def question_list(request):
|
||||||
questions = AnatomyQuestion.objects.all()
|
questions = AnatomyQuestion.objects.all()
|
||||||
return render(request, "anatomy/question_list.html", {"questions": questions})
|
return render(request, "anatomy/question_list.html", {"questions": questions})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def index(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "anatomy/index.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def question_detail(request, pk):
|
def question_detail(request, pk):
|
||||||
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
||||||
@@ -93,38 +88,6 @@ def question_detail(request, pk):
|
|||||||
return render(request, "anatomy/question_detail.html", {"question": question})
|
return render(request, "anatomy/question_detail.html", {"question": question})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_question_detail(request, pk, sk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
question = exam.exam_questions.all()[sk]
|
|
||||||
|
|
||||||
exam_length = len(exam.exam_questions.all())
|
|
||||||
|
|
||||||
pos = exam.get_question_index(question) + 1
|
|
||||||
|
|
||||||
print(question.exams.through.sort_value)
|
|
||||||
|
|
||||||
previous = -1
|
|
||||||
if sk > 0:
|
|
||||||
previous = sk - 1
|
|
||||||
next = sk + 1
|
|
||||||
if sk == exam_length - 1:
|
|
||||||
next = False
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"anatomy/question_detail.html",
|
|
||||||
{
|
|
||||||
"question": question,
|
|
||||||
"exam": exam,
|
|
||||||
"next": next,
|
|
||||||
"previous": previous,
|
|
||||||
"exam_length": exam_length,
|
|
||||||
"pos": pos,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def answer_question(request, pk):
|
def answer_question(request, pk):
|
||||||
@@ -283,63 +246,28 @@ def loadJsonAnswer(answer):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def exam_json_edit(request, pk):
|
#@csrf_exempt
|
||||||
if request.is_ajax() and request.method == "POST":
|
#def postExamAnswers(request):
|
||||||
|
# if request.is_ajax and request.method == "POST":
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
#
|
||||||
|
# n = 0
|
||||||
if request.POST.get("set_open_access") == "true":
|
# # horrible but it works
|
||||||
state = True
|
# #for k in request.POST.dict():
|
||||||
else:
|
#
|
||||||
state = False
|
# for answer in json.loads(request.POST.get("answers")):
|
||||||
|
# ret = loadJsonAnswer(answer)
|
||||||
questions_changed = []
|
#
|
||||||
for q in exam.exam_questions.all():
|
# if ret is not True:
|
||||||
q.open_access = state
|
# return ret
|
||||||
q.save()
|
# n = n + 1
|
||||||
questions_changed.append(q.pk)
|
#
|
||||||
|
# # print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
||||||
data = {"status": "success", "questions": questions_changed, "state": state}
|
# # print(request.urlencode())
|
||||||
return JsonResponse(data, status=200)
|
#
|
||||||
else:
|
# return JsonResponse({"success": True, "question_count": n})
|
||||||
data = {"status": "error"}
|
# return JsonResponse({"success": False, "error": "Invalid data"})
|
||||||
return JsonResponse(data, status=400)
|
#
|
||||||
|
# # return render(request, "anatomy/exam.html", {"exam" : exam, "question" : question})
|
||||||
|
|
||||||
@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})
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
|
||||||
@login_required
|
|
||||||
def mark_overview(request, pk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request, "anatomy/mark_overview.html", {"exam": exam, "questions": questions}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
||||||
@@ -487,116 +415,6 @@ def mark(request, pk, sk):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
AnatomyExamViews = ExamViews(Exam, "anatomy", "anatomy")
|
|
||||||
|
|
||||||
# def exam_toggle_results_published(request, pk):
|
|
||||||
# if request.is_ajax() and request.method == "POST":
|
|
||||||
#
|
|
||||||
# exam = get_object_or_404(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)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def exam_toggle_active(request, pk):
|
|
||||||
# if request.is_ajax() and request.method == "POST":
|
|
||||||
#
|
|
||||||
# exam = get_object_or_404(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)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def active_exams(request, json=True):
|
|
||||||
# exams = 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": "anatomy",
|
|
||||||
# }
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# if json == False:
|
|
||||||
# return active_exams["exams"]
|
|
||||||
#
|
|
||||||
# return JsonResponse(active_exams)
|
|
||||||
#
|
|
||||||
# @login_required
|
|
||||||
# def exam_json_recreate(request, pk):
|
|
||||||
# exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
#
|
|
||||||
# exam.recreate_json = True
|
|
||||||
# exam.save()
|
|
||||||
#
|
|
||||||
# return redirect("anatomy:exam_overview", pk=pk)
|
|
||||||
|
|
||||||
def exam_json(request, pk):
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
if not exam.active:
|
|
||||||
raise Http404("No available exam")
|
|
||||||
|
|
||||||
exam_json_cache = cache.get("anatomy_exam_json_{}".format(pk))
|
|
||||||
|
|
||||||
if exam_json_cache is not None and not exam.recreate_json:
|
|
||||||
exam_json_cache["cached"] = True
|
|
||||||
return JsonResponse(exam_json_cache)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
exam_questions = defaultdict(dict)
|
|
||||||
|
|
||||||
exam_order = []
|
|
||||||
|
|
||||||
for q in questions:
|
|
||||||
exam_order.append(q.id)
|
|
||||||
|
|
||||||
exam_questions[q.id] = {
|
|
||||||
"title": "{}".format(q.description),
|
|
||||||
"question": str(q.question_type),
|
|
||||||
"images": [image_as_base64(q.image)],
|
|
||||||
"annotations": [str(q.image_annotations)],
|
|
||||||
"type": "anatomy",
|
|
||||||
}
|
|
||||||
|
|
||||||
exam_json = {
|
|
||||||
"eid": "anatomy/{}".format(exam.id),
|
|
||||||
"cached": False,
|
|
||||||
"exam_type": "anatomy",
|
|
||||||
"exam_name": exam.name,
|
|
||||||
"exam_mode": True,
|
|
||||||
"exam_order": exam_order,
|
|
||||||
"questions": exam_questions,
|
|
||||||
}
|
|
||||||
|
|
||||||
if exam.time_limit:
|
|
||||||
exam_json["exam_time"] = exam.time_limit
|
|
||||||
|
|
||||||
exam.recreate_json = False
|
|
||||||
exam.save()
|
|
||||||
|
|
||||||
cache.set("anatomy_exam_json_{}".format(pk), exam_json, 3600)
|
|
||||||
|
|
||||||
return JsonResponse(exam_json)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -1116,3 +934,5 @@ def question_save_annotation(request, pk):
|
|||||||
data = {"status": "error"}
|
data = {"status": "error"}
|
||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
AnatomyExamViews = ExamViews(Exam, "anatomy", "anatomy", loadJsonAnswer)
|
||||||
+152
-29
@@ -6,8 +6,18 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
from django.http import Http404, JsonResponse
|
from django.http import Http404, JsonResponse
|
||||||
from django.http import HttpResponseRedirect, HttpResponse
|
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
|
import json
|
||||||
|
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
from .forms import (
|
from .forms import (
|
||||||
ExaminationForm,
|
ExaminationForm,
|
||||||
)
|
)
|
||||||
@@ -40,12 +50,15 @@ def get_examination_id(request):
|
|||||||
return HttpResponse("/")
|
return HttpResponse("/")
|
||||||
|
|
||||||
|
|
||||||
class ExamViews:
|
|
||||||
def __init__(self, exam, app, question_type):
|
class ExamViews(View, LoginRequiredMixin):
|
||||||
|
def __init__(self, exam, app, question_type, loadJsonAnswer):
|
||||||
self.Exam = exam
|
self.Exam = exam
|
||||||
self.app_name = app
|
self.app_name = app
|
||||||
self.question_type = question_type
|
self.question_type = question_type
|
||||||
|
self.loadJsonAnswer = loadJsonAnswer
|
||||||
|
|
||||||
|
@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":
|
||||||
|
|
||||||
@@ -62,6 +75,7 @@ class ExamViews:
|
|||||||
return JsonResponse(data, status=400)
|
return JsonResponse(data, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
@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":
|
||||||
|
|
||||||
@@ -75,6 +89,105 @@ class ExamViews:
|
|||||||
data = {"status": "error"}
|
data = {"status": "error"}
|
||||||
return JsonResponse(data, status=400)
|
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 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)
|
||||||
|
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):
|
def active_exams(self, request, json=True):
|
||||||
exams = self.Exam.objects.all()
|
exams = self.Exam.objects.all()
|
||||||
@@ -96,35 +209,45 @@ class ExamViews:
|
|||||||
|
|
||||||
return JsonResponse(active_exams)
|
return JsonResponse(active_exams)
|
||||||
|
|
||||||
@login_required
|
@method_decorator(csrf_exempt)
|
||||||
def exam_json_recreate(self, request, pk):
|
def postExamAnswers(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)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
exam.recreate_json = True
|
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()
|
exam.save()
|
||||||
|
|
||||||
return redirect("{}:exam_overview".format(self.app_name), pk=pk)
|
cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600)
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_list(self, request):
|
|
||||||
exams = self.Exam.objects.all()
|
|
||||||
return render(request, "{}/exam_list.html".format(self.app_name), {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@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},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
return JsonResponse(exam_json)
|
||||||
+58
-32
@@ -5,7 +5,7 @@ app_name = "longs"
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('', views.question_list, name='question_list'),
|
# path('', views.question_list, name='question_list'),
|
||||||
path("", views.index, name="index"),
|
path("", views.LongExamViews.index, name="index"),
|
||||||
path("author/<int:pk>/", views.author_detail, name="author_detail"),
|
path("author/<int:pk>/", views.author_detail, name="author_detail"),
|
||||||
path("author/", views.author_list, name="author_list"),
|
path("author/", views.author_list, name="author_list"),
|
||||||
path("question/", views.LongView.as_view(), name="long_view"),
|
path("question/", views.LongView.as_view(), name="long_view"),
|
||||||
@@ -20,49 +20,75 @@ urlpatterns = [
|
|||||||
# path("all_questions/", views.all_questions, name="all_questions"),
|
# path("all_questions/", views.all_questions, name="all_questions"),
|
||||||
path("question/<int:pk>/scrap", views.long_scrap, name="long_scrap"),
|
path("question/<int:pk>/scrap", views.long_scrap, name="long_scrap"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.LongExamViews.mark_overview, name="mark_overview"),
|
||||||
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
path("exam/<int:pk>/question/<int:sk>/", views.exam_question_detail, name="exam_question_detail"),
|
path(
|
||||||
path("exam/<int:pk>/", views.exam_overview, name="exam_overview"),
|
"exam/<int:pk>/question/<int:sk>/",
|
||||||
path("exam/<int:pk>/json_edit", views.exam_json_edit, name="exam_json_edit"),
|
views.LongExamViews.exam_question_detail,
|
||||||
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
name="exam_question_detail",
|
||||||
name="exam_scores_cid"),
|
),
|
||||||
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
path("exam/<int:pk>/", views.LongExamViews.exam_overview, name="exam_overview"),
|
||||||
name="exam_scores_cid_user"),
|
path("exam/<int:pk>/json_edit", views.LongExamViews.exam_json_edit, name="exam_json_edit"),
|
||||||
path("exam/<int:pk>/toggle_active", views.exam_toggle_active, name="exam_toggle_active"),
|
path("exam/<int:pk>/scores", views.exam_scores_cid, name="exam_scores_cid"),
|
||||||
path("exam/<int:pk>/toggle_results_published", views.exam_toggle_results_published, name="exam_toggle_results_published"),
|
path(
|
||||||
path("exam/submit", views.postExamAnswers, name="exam_answers_submit"),
|
"exam/<int:pk>/scores/<int:sk>/",
|
||||||
path("exam/", views.exam_list, name="exam_list"),
|
views.exam_scores_cid_user,
|
||||||
path("exam/json/", views.active_exams, name="active_exams"),
|
name="exam_scores_cid_user",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"exam/<int:pk>/toggle_active",
|
||||||
|
views.LongExamViews.exam_toggle_active,
|
||||||
|
name="exam_toggle_active",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"exam/<int:pk>/toggle_results_published",
|
||||||
|
views.LongExamViews.exam_toggle_results_published,
|
||||||
|
name="exam_toggle_results_published",
|
||||||
|
),
|
||||||
|
path("exam/submit", views.LongExamViews.postExamAnswers, name="exam_answers_submit"),
|
||||||
|
path("exam/", views.LongExamViews.exam_list, name="exam_list"),
|
||||||
|
path("exam/json/", views.LongExamViews.active_exams, name="active_exams"),
|
||||||
path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
||||||
path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
path(
|
||||||
|
"exam/json/<int:pk>/recreate",
|
||||||
|
views.LongExamViews.exam_json_recreate,
|
||||||
|
name="exam_json_recreate",
|
||||||
|
),
|
||||||
path("create/", views.LongCreate.as_view(), name="long_create"),
|
path("create/", views.LongCreate.as_view(), name="long_create"),
|
||||||
path("create/series", views.LongSeriesCreate.as_view(), name="long_series_create"),
|
path("create/series", views.LongSeriesCreate.as_view(), name="long_series_create"),
|
||||||
path("create/series/<int:pk>", views.LongSeriesCreate.as_view(), name="long_series_id_create"),
|
path(
|
||||||
path("create/defaults",
|
"create/series/<int:pk>",
|
||||||
|
views.LongSeriesCreate.as_view(),
|
||||||
|
name="long_series_id_create",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"create/defaults",
|
||||||
views.LongCreationDefaultView.as_view(),
|
views.LongCreationDefaultView.as_view(),
|
||||||
name="long_create_defaults"),
|
name="long_create_defaults",
|
||||||
|
),
|
||||||
path("region/create/", views.create_region, name="create_region"),
|
path("region/create/", views.create_region, name="create_region"),
|
||||||
path("region/ajax/get_region_id",
|
path("region/ajax/get_region_id", views.get_region_id, name="get_region_id"),
|
||||||
views.get_region_id,
|
path("abnormality/create/", views.create_abnormality, name="create_abnormality"),
|
||||||
name="get_region_id"),
|
path(
|
||||||
path("abnormality/create/",
|
"abnormality/ajax/get_abnormality_id",
|
||||||
views.create_abnormality,
|
|
||||||
name="create_abnormality"),
|
|
||||||
path("abnormality/ajax/get_abnormality_id",
|
|
||||||
views.get_abnormality_id,
|
views.get_abnormality_id,
|
||||||
name="get_abnormality_id"),
|
name="get_abnormality_id",
|
||||||
path("examination/create/",
|
),
|
||||||
views.create_examination,
|
path("examination/create/", views.create_examination, name="create_examination"),
|
||||||
name="create_examination"),
|
path(
|
||||||
path("examination/ajax/get_examination_id",
|
"examination/ajax/get_examination_id",
|
||||||
views.get_examination_id,
|
views.get_examination_id,
|
||||||
name="get_examination_id"),
|
name="get_examination_id",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"question/<int:pk>/update",
|
"question/<int:pk>/update",
|
||||||
views.LongUpdate.as_view(),
|
views.LongUpdate.as_view(),
|
||||||
name="long_update",
|
name="long_update",
|
||||||
),
|
),
|
||||||
path("series/<int:pk>/update", views.LongSeriesUpdate.as_view(), name="long_series_update"),
|
path(
|
||||||
|
"series/<int:pk>/update",
|
||||||
|
views.LongSeriesUpdate.as_view(),
|
||||||
|
name="long_series_update",
|
||||||
|
),
|
||||||
path("<int:pk>/add_note", views.AddNote.as_view(), name="long_add_note"),
|
path("<int:pk>/add_note", views.AddNote.as_view(), name="long_add_note"),
|
||||||
]
|
]
|
||||||
|
|||||||
+4
-178
@@ -56,6 +56,8 @@ from django.forms.models import model_to_dict
|
|||||||
from longs.forms import LongCreationDefaultForm
|
from longs.forms import LongCreationDefaultForm
|
||||||
from longs.models import LongCreationDefault
|
from longs.models import LongCreationDefault
|
||||||
|
|
||||||
|
from generic.views import ExamViews
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -69,11 +71,6 @@ class AuthorOrCheckerRequiredMixin(object):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def index(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "longs/index.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
# def index(request):
|
# def index(request):
|
||||||
# other_longs = Long.objects.exclude(author=request.user.pk)
|
# other_longs = Long.objects.exclude(author=request.user.pk)
|
||||||
@@ -652,62 +649,6 @@ def loadJsonAnswer(answer):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def exam_json_edit(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
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)
|
|
||||||
else:
|
|
||||||
data = {"status": "error"}
|
|
||||||
return JsonResponse(data, status=400)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def postExamAnswers(request):
|
|
||||||
if request.is_ajax and request.method == "POST":
|
|
||||||
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
for answer in json.loads(request.POST.get("answers")):
|
|
||||||
ret = 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"})
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
|
||||||
@login_required
|
|
||||||
def mark_overview(request, pk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request, "longs/mark_overview.html", {"exam": exam, "questions": questions}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
||||||
@login_required
|
@login_required
|
||||||
@@ -855,56 +796,6 @@ def mark(request, pk, sk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_results_published(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_active(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def active_exams(request, json=True):
|
|
||||||
exams = 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": "long",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if json == False:
|
|
||||||
return active_exams["exams"]
|
|
||||||
|
|
||||||
return JsonResponse(active_exams)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_json(request, pk):
|
def exam_json(request, pk):
|
||||||
|
|
||||||
@@ -962,6 +853,7 @@ def exam_json(request, pk):
|
|||||||
"questions": exam_questions,
|
"questions": exam_questions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if exam.time_limit:
|
if exam.time_limit:
|
||||||
exam_json["exam_time"] = exam.time_limit
|
exam_json["exam_time"] = exam.time_limit
|
||||||
|
|
||||||
@@ -973,16 +865,6 @@ def exam_json(request, pk):
|
|||||||
return JsonResponse(exam_json)
|
return JsonResponse(exam_json)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_json_recreate(request, pk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
exam.recreate_json = True
|
|
||||||
exam.save()
|
|
||||||
|
|
||||||
return redirect("longs:exam_overview", pk=pk)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def exam_scores_cid(request, pk):
|
def exam_scores_cid(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
@@ -1155,60 +1037,4 @@ def exam_scores_cid_user(request, pk, sk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
LongExamViews = ExamViews(Exam, "longs", "long", loadJsonAnswer)
|
||||||
def exam_question_detail(request, pk, sk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
question = exam.exam_questions.all()[sk]
|
|
||||||
|
|
||||||
exam_length = len(exam.exam_questions.all())
|
|
||||||
|
|
||||||
pos = exam.get_question_index(question) + 1
|
|
||||||
|
|
||||||
print(question.exams.through.sort_value)
|
|
||||||
|
|
||||||
previous = -1
|
|
||||||
if sk > 0:
|
|
||||||
previous = sk - 1
|
|
||||||
next = sk + 1
|
|
||||||
if sk == exam_length - 1:
|
|
||||||
next = False
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"longs/long_detail.html",
|
|
||||||
{
|
|
||||||
"question": question,
|
|
||||||
"exam": exam,
|
|
||||||
"next": next,
|
|
||||||
"previous": previous,
|
|
||||||
"exam_length": exam_length,
|
|
||||||
"pos": pos,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_list(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "longs/exam_list.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_overview(request, pk):
|
|
||||||
print(type(pk))
|
|
||||||
#print(Exam.objects.all())
|
|
||||||
#exams = Exam.objects.all()
|
|
||||||
#print("test", Exam.objects.all().get(id=pk))
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
print("exam", exam)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
question_number = len(questions)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"longs/exam_overview.html",
|
|
||||||
{"exam": exam, "questions": questions, "question_number": question_number},
|
|
||||||
)
|
|
||||||
@@ -110,7 +110,12 @@
|
|||||||
ans: answers
|
ans: answers
|
||||||
}
|
}
|
||||||
|
|
||||||
postAnswers(ans);
|
let json = {
|
||||||
|
eid: {{exam.pk}},
|
||||||
|
answers: JSON.stringify([ans]),
|
||||||
|
};
|
||||||
|
|
||||||
|
postAnswers(json);
|
||||||
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -125,7 +130,7 @@
|
|||||||
|
|
||||||
function postAnswers(ans) {
|
function postAnswers(ans) {
|
||||||
console.log(ans);
|
console.log(ans);
|
||||||
$.post("{% url 'physics:exam_answers_submit' %}", JSON.stringify(ans)).done((data) => {
|
$.post("{% url 'physics:exam_answers_submit' %}", ans, null, "json").done((data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
let ret = confirm(
|
let ret = confirm(
|
||||||
|
|||||||
+6
-6
@@ -5,7 +5,7 @@ app_name = "physics"
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('', views.question_list, name='question_list'),
|
# path('', views.question_list, name='question_list'),
|
||||||
path("", views.index, name="index"),
|
path("", views.PhysicsExamViews.index, name="index"),
|
||||||
#path("question/", views.QuestionView.as_view(), name="question_view"),
|
#path("question/", views.QuestionView.as_view(), name="question_view"),
|
||||||
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
||||||
#path("question/create/", views.QuestionCreate.as_view(), name="anatomy_question_create"),
|
#path("question/create/", views.QuestionCreate.as_view(), name="anatomy_question_create"),
|
||||||
@@ -13,15 +13,15 @@ urlpatterns = [
|
|||||||
#path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
#path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
#path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
#path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
||||||
path("exam/<int:pk>/take", views.exam_take, name="exam_take"),
|
path("exam/<int:pk>/take", views.exam_take, name="exam_take"),
|
||||||
path("exam/<int:pk>/", views.exam_overview, name="exam_overview"),
|
path("exam/<int:pk>/", views.PhysicsExamViews.exam_overview, name="exam_overview"),
|
||||||
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
||||||
name="exam_scores_cid"),
|
name="exam_scores_cid"),
|
||||||
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
||||||
name="exam_scores_cid_user"),
|
name="exam_scores_cid_user"),
|
||||||
path("exam/<int:pk>/toggle_active", views.exam_toggle_active, name="exam_toggle_active"),
|
path("exam/<int:pk>/toggle_active", views.PhysicsExamViews.exam_toggle_active, name="exam_toggle_active"),
|
||||||
path("exam/<int:pk>/toggle_results_published", views.exam_toggle_results_published, name="exam_toggle_results_published"),
|
path("exam/<int:pk>/toggle_results_published", views.PhysicsExamViews.exam_toggle_results_published, name="exam_toggle_results_published"),
|
||||||
path("exam/submit", views.postExamAnswers, name="exam_answers_submit"),
|
path("exam/submit", views.PhysicsExamViews.postExamAnswers, name="exam_answers_submit"),
|
||||||
path("exam/", views.exam_list, name="exam_list"),
|
path("exam/", views.PhysicsExamViews.exam_list, name="exam_list"),
|
||||||
path("exam/available", views.active_exams, name="active_exams"),
|
path("exam/available", views.active_exams, name="active_exams"),
|
||||||
#path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
#path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
||||||
#path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
#path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
||||||
|
|||||||
+4
-82
@@ -31,80 +31,20 @@ import json
|
|||||||
import statistics
|
import statistics
|
||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
|
|
||||||
|
from generic.views import ExamViews
|
||||||
|
|
||||||
|
|
||||||
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})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def index(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "physics/index.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def question_detail(request, pk):
|
def question_detail(request, pk):
|
||||||
question = get_object_or_404(Question, pk=pk)
|
question = get_object_or_404(Question, pk=pk)
|
||||||
return render(request, "physics/question_detail.html", {"question": question})
|
return render(request, "physics/question_detail.html", {"question": question})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_list(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "physics/exam_list.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_overview(request, pk):
|
|
||||||
print(type(pk))
|
|
||||||
print(Exam.objects.all())
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
print("test", Exam.objects.all().get(id=pk))
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
print("exam", exam)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
question_number = len(questions)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"physics/exam_overview.html",
|
|
||||||
{"exam": exam, "questions": questions, "question_number": question_number},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_results_published(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_active(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def active_exams(request):
|
def active_exams(request):
|
||||||
exams = Exam.objects.all()
|
exams = Exam.objects.all()
|
||||||
print(exams)
|
print(exams)
|
||||||
@@ -289,26 +229,6 @@ def exam_take(request, pk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@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():
|
|
||||||
print(k)
|
|
||||||
ret = loadJsonAnswer(json.loads(k))
|
|
||||||
|
|
||||||
if ret is not True:
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
|
|
||||||
# print(request.urlencode())
|
|
||||||
|
|
||||||
return JsonResponse({"success": True})
|
|
||||||
return JsonResponse({"success": False, "error": "Invalid data"})
|
|
||||||
|
|
||||||
|
|
||||||
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)):
|
||||||
@@ -364,3 +284,5 @@ def loadJsonAnswer(answer):
|
|||||||
ans.save()
|
ans.save()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
PhysicsExamViews = ExamViews(Exam, "physics", "physics", loadJsonAnswer)
|
||||||
+10
-5
@@ -30,8 +30,9 @@ from anatomy.models import Exam as AnatomyExam
|
|||||||
from rapids.models import CidUserAnswer as RapidsCidUserAnswer
|
from rapids.models import CidUserAnswer as RapidsCidUserAnswer
|
||||||
from rapids.models import Exam as RapidsExam
|
from rapids.models import Exam as RapidsExam
|
||||||
|
|
||||||
from anatomy.views import AnatomyExamViews as AnatomyExamViews, postExamAnswers as postAnatomyExamAnswers
|
from anatomy.views import AnatomyExamViews
|
||||||
from rapids.views import active_exams as active_rapid_exams, postExamAnswers as postRapidExamAnswers
|
from rapids.views import RapidExamViews
|
||||||
|
from longs.views import LongExamViews
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -89,11 +90,13 @@ def cid_scores(request, pk):
|
|||||||
|
|
||||||
def active_exams(request):
|
def active_exams(request):
|
||||||
anatomy_exams = AnatomyExamViews.active_exams(request, False)
|
anatomy_exams = AnatomyExamViews.active_exams(request, False)
|
||||||
rapid_exams = active_rapid_exams(request, False)
|
rapid_exams = RapidExamViews.active_exams(request, False)
|
||||||
|
long_exams = LongExamViews.active_exams(request, False)
|
||||||
|
|
||||||
exams = []
|
exams = []
|
||||||
exams.extend(anatomy_exams)
|
exams.extend(anatomy_exams)
|
||||||
exams.extend(rapid_exams)
|
exams.extend(rapid_exams)
|
||||||
|
exams.extend(long_exams)
|
||||||
|
|
||||||
active_exams = {"exams": exams}
|
active_exams = {"exams": exams}
|
||||||
|
|
||||||
@@ -107,9 +110,11 @@ def exam_submit(request):
|
|||||||
exam_type, exam_id = request.POST.get("eid").split("/")
|
exam_type, exam_id = request.POST.get("eid").split("/")
|
||||||
|
|
||||||
if exam_type == "anatomy":
|
if exam_type == "anatomy":
|
||||||
return postAnatomyExamAnswers(request)
|
return AnatomyExamViews.postExamAnswers(request)
|
||||||
elif exam_type == "rapid":
|
elif exam_type == "rapid":
|
||||||
return postRapidExamAnswers(request)
|
return RapidExamViews.postExamAnswers(request)
|
||||||
|
elif exam_type == "long":
|
||||||
|
return LongExamViews.postExamAnswers(request)
|
||||||
return JsonResponse({"success": False, "error": "Invalid exam type"})
|
return JsonResponse({"success": False, "error": "Invalid exam type"})
|
||||||
|
|
||||||
# postExamAnswers
|
# postExamAnswers
|
||||||
|
|||||||
+11
-11
@@ -5,7 +5,7 @@ app_name = "rapids"
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('', views.question_list, name='question_list'),
|
# path('', views.question_list, name='question_list'),
|
||||||
path("", views.index, name="index"),
|
path("", views.RapidExamViews.index, name="index"),
|
||||||
path("author/<int:pk>/", views.author_detail, name="author_detail"),
|
path("author/<int:pk>/", views.author_detail, name="author_detail"),
|
||||||
path("author/", views.author_list, name="author_list"),
|
path("author/", views.author_list, name="author_list"),
|
||||||
path("question/", views.RapidView.as_view(), name="rapid_view"),
|
path("question/", views.RapidView.as_view(), name="rapid_view"),
|
||||||
@@ -18,22 +18,22 @@ urlpatterns = [
|
|||||||
#path("all_questions/", views.all_questions, name="all_questions"),
|
#path("all_questions/", views.all_questions, name="all_questions"),
|
||||||
path("question/<int:pk>/scrap", views.rapid_scrap, name="rapid_scrap"),
|
path("question/<int:pk>/scrap", views.rapid_scrap, name="rapid_scrap"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.RapidExamViews.mark_overview, name="mark_overview"),
|
||||||
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
path("exam/<int:pk>/question/<int:sk>/", views.exam_question_detail, name="exam_question_detail"),
|
path("exam/<int:pk>/question/<int:sk>/", views.RapidExamViews.exam_question_detail, name="exam_question_detail"),
|
||||||
path("exam/<int:pk>/", views.exam_overview, name="exam_overview"),
|
path("exam/<int:pk>/", views.RapidExamViews.exam_overview, name="exam_overview"),
|
||||||
path("exam/<int:pk>/json_edit", views.exam_json_edit, name="exam_json_edit"),
|
path("exam/<int:pk>/json_edit", views.RapidExamViews.exam_json_edit, name="exam_json_edit"),
|
||||||
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
||||||
name="exam_scores_cid"),
|
name="exam_scores_cid"),
|
||||||
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
path("exam/<int:pk>/scores/<int:sk>/", views.exam_scores_cid_user,
|
||||||
name="exam_scores_cid_user"),
|
name="exam_scores_cid_user"),
|
||||||
path("exam/<int:pk>/toggle_active", views.exam_toggle_active, name="exam_toggle_active"),
|
path("exam/<int:pk>/toggle_active", views.RapidExamViews.exam_toggle_active, name="exam_toggle_active"),
|
||||||
path("exam/<int:pk>/toggle_results_published", views.exam_toggle_results_published, name="exam_toggle_results_published"),
|
path("exam/<int:pk>/toggle_results_published", views.RapidExamViews.exam_toggle_results_published, name="exam_toggle_results_published"),
|
||||||
path("exam/submit", views.postExamAnswers, name="exam_answers_submit"),
|
path("exam/submit", views.RapidExamViews.postExamAnswers, name="exam_answers_submit"),
|
||||||
path("exam/", views.exam_list, name="exam_list"),
|
path("exam/", views.RapidExamViews.exam_list, name="exam_list"),
|
||||||
path("exam/json/", views.active_exams, name="active_exams"),
|
path("exam/json/", views.RapidExamViews.active_exams, name="active_exams"),
|
||||||
path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
||||||
path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
path("exam/json/<int:pk>/recreate", views.RapidExamViews.exam_json_recreate, name="exam_json_recreate"),
|
||||||
path("create/", views.RapidCreate.as_view(), name="rapid_create"),
|
path("create/", views.RapidCreate.as_view(), name="rapid_create"),
|
||||||
path("create/defaults",
|
path("create/defaults",
|
||||||
views.RapidCreationDefaultView.as_view(),
|
views.RapidCreationDefaultView.as_view(),
|
||||||
|
|||||||
+4
-188
@@ -39,6 +39,9 @@ from .models import (
|
|||||||
Answer,
|
Answer,
|
||||||
CidUserAnswer,
|
CidUserAnswer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from generic.views import ExamViews
|
||||||
|
|
||||||
from .tables import RapidTable
|
from .tables import RapidTable
|
||||||
from .filters import RapidFilter
|
from .filters import RapidFilter
|
||||||
|
|
||||||
@@ -75,20 +78,6 @@ class AuthorOrCheckerRequiredMixin(object):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def index(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "rapids/index.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
# def index(request):
|
|
||||||
# other_rapids = Rapid.objects.exclude(author=request.user.pk)
|
|
||||||
# user_rapids = Rapid.objects.filter(author=request.user.pk)
|
|
||||||
# return render(
|
|
||||||
# request,
|
|
||||||
# "rapids/index.html",
|
|
||||||
# {"other_rapids": other_rapids, "user_rapids": user_rapids},
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -564,63 +553,6 @@ def loadJsonAnswer(answer):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def exam_json_edit(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
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)
|
|
||||||
else:
|
|
||||||
data = {"status": "error"}
|
|
||||||
return JsonResponse(data, status=400)
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def postExamAnswers(request):
|
|
||||||
if request.is_ajax and request.method == "POST":
|
|
||||||
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
for answer in json.loads(request.POST.get("answers")):
|
|
||||||
ret = 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"})
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
|
||||||
@login_required
|
|
||||||
def mark_overview(request, pk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request, "rapids/mark_overview.html", {"exam": exam, "questions": questions}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
# @user_passes_test(user_is_admin, login_url="/accounts/login")
|
||||||
@login_required
|
@login_required
|
||||||
def mark(request, pk, sk):
|
def mark(request, pk, sk):
|
||||||
@@ -767,57 +699,6 @@ def mark(request, pk, sk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_results_published(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_toggle_active(request, pk):
|
|
||||||
if request.is_ajax() and request.method == "POST":
|
|
||||||
|
|
||||||
exam = get_object_or_404(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)
|
|
||||||
|
|
||||||
|
|
||||||
def active_exams(request, json=True):
|
|
||||||
exams = 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": "rapid",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if json == False:
|
|
||||||
return active_exams["exams"]
|
|
||||||
|
|
||||||
return JsonResponse(active_exams)
|
|
||||||
|
|
||||||
|
|
||||||
def exam_json(request, pk):
|
def exam_json(request, pk):
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
@@ -885,16 +766,6 @@ def exam_json(request, pk):
|
|||||||
return JsonResponse(exam_json)
|
return JsonResponse(exam_json)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_json_recreate(request, pk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
exam.recreate_json = True
|
|
||||||
exam.save()
|
|
||||||
|
|
||||||
return redirect("rapids:exam_overview", pk=pk)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def exam_scores_cid(request, pk):
|
def exam_scores_cid(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
@@ -1067,60 +938,5 @@ def exam_scores_cid_user(request, pk, sk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_question_detail(request, pk, sk):
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
|
|
||||||
question = exam.exam_questions.all()[sk]
|
RapidExamViews = ExamViews(Exam, "rapids", "rapid", loadJsonAnswer)
|
||||||
|
|
||||||
exam_length = len(exam.exam_questions.all())
|
|
||||||
|
|
||||||
pos = exam.get_question_index(question) + 1
|
|
||||||
|
|
||||||
print(question.exams.through.sort_value)
|
|
||||||
|
|
||||||
previous = -1
|
|
||||||
if sk > 0:
|
|
||||||
previous = sk - 1
|
|
||||||
next = sk + 1
|
|
||||||
if sk == exam_length - 1:
|
|
||||||
next = False
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"rapids/rapid_detail.html",
|
|
||||||
{
|
|
||||||
"question": question,
|
|
||||||
"exam": exam,
|
|
||||||
"next": next,
|
|
||||||
"previous": previous,
|
|
||||||
"exam_length": exam_length,
|
|
||||||
"pos": pos,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_list(request):
|
|
||||||
exams = Exam.objects.all()
|
|
||||||
return render(request, "rapids/exam_list.html", {"exams": exams})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def exam_overview(request, pk):
|
|
||||||
print(type(pk))
|
|
||||||
#print(Exam.objects.all())
|
|
||||||
#exams = Exam.objects.all()
|
|
||||||
#print("test", Exam.objects.all().get(id=pk))
|
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
|
||||||
print("exam", exam)
|
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
|
||||||
|
|
||||||
question_number = len(questions)
|
|
||||||
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"rapids/exam_overview.html",
|
|
||||||
{"exam": exam, "questions": questions, "question_number": question_number},
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user