continue unifying views

This commit is contained in:
Ross
2021-02-07 22:43:17 +00:00
parent 3712cf15fc
commit 8fbb50ee9f
12 changed files with 330 additions and 752 deletions
+35
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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},
)
+7 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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},
)