unify generic exam views naming

This commit is contained in:
Ross
2021-12-19 10:08:07 +00:00
parent b823e0a897
commit 889db68a08
12 changed files with 194 additions and 133 deletions
+18 -18
View File
@@ -8,7 +8,7 @@ app_name = "anatomy"
urlpatterns = [
# path('', views.question_list, name='question_list'),
path("", views.AnatomyExamViews.index, name="index"),
path("", views.GenericExamViews.index, name="index"),
path(
"question/",
views.AnatomyQuestionView.as_view(),
@@ -62,29 +62,29 @@ urlpatterns = [
"exam/<int:exam_pk>/<int:sk>/mark/review", views.mark_review, name="mark_review"
),
path(
"exam/<int:pk>/mark", views.AnatomyExamViews.mark_overview, name="mark_overview"
"exam/<int:pk>/mark", views.GenericExamViews.mark_overview, name="mark_overview"
),
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
path(
"exam/<int:pk>/question/<int:sk>/",
views.AnatomyExamViews.exam_question_detail,
views.GenericExamViews.exam_question_detail,
name="exam_question_detail",
),
path("exam/<int:pk>/", views.AnatomyExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path(
"exam/<int:pk>/json_edit",
views.AnatomyExamViews.exam_json_edit,
views.GenericExamViews.exam_json_edit,
name="exam_json_edit",
),
path(
"exam/<int:pk>/scores",
views.AnatomyExamViews.exam_scores_cid,
views.GenericExamViews.exam_scores_cid,
# cache_page(60 * 1)(views.exam_scores_cid),
name="exam_scores_cid",
),
path(
"exam/<int:pk>/scores/refresh",
views.AnatomyExamViews.exam_scores_refresh,
views.GenericExamViews.exam_scores_refresh,
# cache_page(60 * 1)(views.exam_scores_cid),
name="exam_scores_refresh",
),
@@ -95,41 +95,41 @@ urlpatterns = [
),
path(
"exam/<int:pk>/toggle_active",
views.AnatomyExamViews.exam_toggle_active,
views.GenericExamViews.exam_toggle_active,
name="exam_toggle_active",
),
path(
"exam/<int:pk>/toggle_results_published",
views.AnatomyExamViews.exam_toggle_results_published,
views.GenericExamViews.exam_toggle_results_published,
name="exam_toggle_results_published",
),
path(
"exam/submit",
views.AnatomyExamViews.postExamAnswers,
views.GenericExamViews.postExamAnswers,
name="exam_answers_submit",
),
path("exam/", views.AnatomyExamViews.exam_list, name="exam_list"),
path("exam/all", views.AnatomyExamViews.exam_list_all, name="exam_list_all"),
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
path("exam/<int:exam_id>/cids", views.AnatomyExamViews.exam_cids, name="exam_cids"),
path("exam/<int:exam_id>/cids", views.GenericExamViews.exam_cids, name="exam_cids"),
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
path("exam/json/", views.AnatomyExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.AnatomyExamViews.exam_json, name="exam_json"),
path("exam/json/", views.GenericExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.GenericExamViews.exam_json, name="exam_json"),
path(
"exam/json/<int:pk>/unbased",
views.AnatomyExamViews.exam_json_unbased,
views.GenericExamViews.exam_json_unbased,
name="exam_json_unbased",
),
path(
"exam/json/<int:pk>/<int:sk>/unbased",
views.AnatomyExamViews.exam_question_json_unbased,
views.GenericExamViews.exam_question_json_unbased,
name="exam_question_json_unbased",
),
path(
"exam/json/<int:pk>/recreate",
views.AnatomyExamViews.exam_json_recreate,
views.GenericExamViews.exam_json_recreate,
name="exam_json_recreate",
),
# path("cid/", views.cid_selector, name="cid_selector"),
+12 -10
View File
@@ -136,8 +136,8 @@ def answer_question(request, pk):
)
#@login_required
#def exam_take(request, pk, sk):
# @login_required
# def exam_take(request, pk, sk):
# """
# Allows taking of the exam on the django server (when logged in)
#
@@ -212,7 +212,7 @@ def answer_question(request, pk):
# )
#def flag_question(request):
# def flag_question(request):
# pk = request.GET.get("pk", None)
# ans = UserAnswer.objects.filter(user=request.user, question__pk=pk).first()
# ans.flagged = not ans.flagged
@@ -244,7 +244,9 @@ def loadJsonAnswer(answer):
exam = get_object_or_404(Exam, pk=eid)
if not exam.check_cid_user(answer["cid"], answer["passcode"]):
return False, JsonResponse({"success": False, "error": "invalid cid / passcode"})
return False, JsonResponse(
{"success": False, "error": "invalid cid / passcode"}
)
# if not exam.active:
# return False, JsonResponse(
@@ -452,6 +454,7 @@ def mark(request, exam_pk, sk, unmarked_exam_answers_only=True, review=False):
},
)
@login_required
def exam_scores_refresh(request, pk):
exam = get_object_or_404(Exam, pk=pk)
@@ -461,9 +464,7 @@ def exam_scores_refresh(request, pk):
questions = exam.exam_questions.all()
cids = (
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
)
cids = CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
# Force a score update
for c in cids:
@@ -477,8 +478,9 @@ def exam_scores_refresh(request, pk):
},
)
#@login_required
#def exam_scores_cid(request, pk):
# @login_required
# def exam_scores_cid(request, pk):
# exam = get_object_or_404(Exam, pk=pk)
#
# if not exam.exam_mode:
@@ -1001,7 +1003,7 @@ def question_save_annotation(request, pk):
return JsonResponse(data, status=400)
AnatomyExamViews = ExamViews(
GenericExamViews = ExamViews(
Exam, AnatomyQuestion, CidUserAnswer, "anatomy", "anatomy", loadJsonAnswer
)
+1
View File
@@ -856,6 +856,7 @@ class ExamViews(View, LoginRequiredMixin):
cache.set("{}_question_json_{}".format(self.app_name, sk), question_json, 3600)
return JsonResponse(question_json)
def exam_scores_cid(self, request, pk):
exam = get_object_or_404(self.Exam, pk=pk)
+20 -16
View File
@@ -5,7 +5,7 @@ app_name = "longs"
urlpatterns = [
# path('', views.question_list, name='question_list'),
path("", views.LongExamViews.index, name="index"),
path("", views.GenericExamViews.index, name="index"),
path("author/<int:pk>/", views.author_detail, name="author_detail"),
path("author/", views.author_list, name="author_list"),
path("question/", views.LongView.as_view(), name="long_view"),
@@ -81,17 +81,19 @@ urlpatterns = [
views.mark_question_overview,
name="mark_question_overview",
),
path("exam/<int:pk>/mark", views.LongExamViews.mark_overview, name="mark_overview"),
path(
"exam/<int:pk>/mark", views.GenericExamViews.mark_overview, name="mark_overview"
),
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
path(
"exam/<int:pk>/question/<int:sk>/",
views.LongExamViews.exam_question_detail,
views.GenericExamViews.exam_question_detail,
name="exam_question_detail",
),
path("exam/<int:pk>/", views.LongExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path(
"exam/<int:pk>/json_edit",
views.LongExamViews.exam_json_edit,
views.GenericExamViews.exam_json_edit,
name="exam_json_edit",
),
path(
@@ -107,43 +109,45 @@ urlpatterns = [
),
path(
"exam/<int:pk>/toggle_active",
views.LongExamViews.exam_toggle_active,
views.GenericExamViews.exam_toggle_active,
name="exam_toggle_active",
),
path(
"exam/<int:pk>/toggle_results_published",
views.LongExamViews.exam_toggle_results_published,
views.GenericExamViews.exam_toggle_results_published,
name="exam_toggle_results_published",
),
path(
"exam/submit", views.LongExamViews.postExamAnswers, name="exam_answers_submit"
"exam/submit",
views.GenericExamViews.postExamAnswers,
name="exam_answers_submit",
),
path("exam/", views.LongExamViews.exam_list, name="exam_list"),
path("exam/all", views.LongExamViews.exam_list_all, name="exam_list_all"),
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
path("exam/json/", views.LongExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.LongExamViews.exam_json, name="exam_json"),
path("exam/json/", views.GenericExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.GenericExamViews.exam_json, name="exam_json"),
path(
"exam/json/<int:pk>/unbased",
views.LongExamViews.exam_json_unbased,
views.GenericExamViews.exam_json_unbased,
name="exam_json_unbased",
),
path(
"exam/json/<int:pk>/<int:sk>",
views.LongExamViews.exam_question_json,
views.GenericExamViews.exam_question_json,
name="exam_question_json",
),
path(
"exam/json/<int:pk>/unbased/<int:sk>",
views.LongExamViews.exam_question_json_unbased,
views.GenericExamViews.exam_question_json_unbased,
name="exam_question_json_unbased",
),
path(
"exam/json/<int:pk>/recreate",
views.LongExamViews.exam_json_recreate,
views.GenericExamViews.exam_json_recreate,
name="exam_json_recreate",
),
path("create/", views.LongCreate.as_view(), name="long_create"),
+5 -4
View File
@@ -315,7 +315,6 @@ class LongSeriesCreate(RevisionMixin, LoginRequiredMixin, CreateView):
kwargs.update({"user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(LongSeriesCreate, self).get_context_data(**kwargs)
@@ -635,7 +634,9 @@ def loadJsonAnswer(answer):
exam = get_object_or_404(Exam, pk=eid)
if not exam.check_cid_user(answer["cid"], answer["passcode"]):
return False, JsonResponse({"success": False, "error": "invalid cid / passcode"})
return False, JsonResponse(
{"success": False, "error": "invalid cid / passcode"}
)
# if not exam.active:
# return False, JsonResponse(
@@ -1107,7 +1108,7 @@ def exam_scores_cid_user(request, pk, sk, passcode):
{
"exam": exam,
"cid": cid,
"passcode" : passcode,
"passcode": passcode,
"questions": questions,
# "answers": answers,
"answers_marks": answers_marks,
@@ -1169,7 +1170,7 @@ def long_series_order_upload_filename(request, pk):
return redirect("longs:long_series_detail", pk=pk)
LongExamViews = ExamViews(Exam, Long, CidUserAnswer, "longs", "long", loadJsonAnswer)
GenericExamViews = ExamViews(Exam, Long, CidUserAnswer, "longs", "long", loadJsonAnswer)
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
+46 -20
View File
@@ -5,34 +5,60 @@ app_name = "physics"
urlpatterns = [
# path('', views.question_list, name='question_list'),
path("", views.PhysicsExamViews.index, name="index"),
#path("question/", views.QuestionView.as_view(), name="question_view"),
path("", views.GenericExamViews.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/create/", views.QuestionCreate.as_view(), name="anatomy_question_create"),
#path("question/<int:pk>/update", views.QuestionUpdate.as_view(), name="anatomy_question_update"),
#path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
#path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
# path("question/create/", views.QuestionCreate.as_view(), name="anatomy_question_create"),
# path("question/<int:pk>/update", views.QuestionUpdate.as_view(), name="anatomy_question_update"),
# 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>/take_old", views.exam_take_old, name="exam_take_old"),
path("exam/<int:pk>/<int:sk>/<str:cid>/<str:passcode>/take", views.exam_take, name="exam_take"),
path(
"exam/<int:pk>/<int:sk>/<str:cid>/<str:passcode>/take",
views.exam_take,
name="exam_take",
),
path("exam/<int:pk>/start", views.exam_start, name="exam_start"),
path("exam/<int:pk>/<str:cid>/<str:passcode>/finish", views.exam_finish, name="exam_finish"),
path("exam/<int:pk>/", views.PhysicsExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/scores", views.exam_scores_cid,
name="exam_scores_cid"),
path("exam/<int:pk>/scores/<int:cid>/<str:passcode>/", views.exam_scores_cid_user,
name="exam_scores_cid_user"),
path("exam/<int:pk>/toggle_active", views.PhysicsExamViews.exam_toggle_active, name="exam_toggle_active"),
path("exam/<int:pk>/toggle_results_published", views.PhysicsExamViews.exam_toggle_results_published, name="exam_toggle_results_published"),
path(
"exam/<int:pk>/<str:cid>/<str:passcode>/finish",
views.exam_finish,
name="exam_finish",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/scores", views.exam_scores_cid, name="exam_scores_cid"),
path(
"exam/<int:pk>/scores/<int:cid>/<str:passcode>/",
views.exam_scores_cid_user,
name="exam_scores_cid_user",
),
path(
"exam/<int:pk>/toggle_active",
views.GenericExamViews.exam_toggle_active,
name="exam_toggle_active",
),
path(
"exam/<int:pk>/toggle_results_published",
views.GenericExamViews.exam_toggle_results_published,
name="exam_toggle_results_published",
),
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
path("exam/submit", views.PhysicsExamViews.postExamAnswers, name="exam_answers_submit"),
path("exam/", views.PhysicsExamViews.exam_list, name="exam_list"),
path(
"exam/submit",
views.GenericExamViews.postExamAnswers,
name="exam_answers_submit",
),
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
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>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
path("user_answers/", views.UserAnswerTableView.as_view(), name="user_answer_table_view"),
# 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(
"user_answers/",
views.UserAnswerTableView.as_view(),
name="user_answer_table_view",
),
path(
"user_answers/<int:pk>", views.UserAnswerView.as_view(), name="user_answer_view"
),
+1 -1
View File
@@ -463,7 +463,7 @@ def loadJsonAnswer(answer):
return True, None
PhysicsExamViews = ExamViews(
GenericExamViews = ExamViews(
Exam, Question, CidUserAnswer, "physics", "physics", loadJsonAnswer
)
+26 -23
View File
@@ -47,9 +47,9 @@ from sbas.models import CidUserAnswer as SbasCidUserAnswer
from sbas.models import Exam as SbasExam
from sbas.models import Question as SbasQuestion
from anatomy.views import AnatomyExamViews
from rapids.views import RapidExamViews
from longs.views import LongExamViews
from anatomy.views import GenericExamViews
from rapids.views import GenericExamViews
from longs.views import GenericExamViews
from generic.forms import QuestionNoteForm
from generic.models import CidUser, QuestionNote
@@ -75,6 +75,7 @@ def cid_selector(request):
"cid_selector.html",
)
@login_required
@user_passes_test(lambda u: u.is_superuser)
def cid_scores_admin(request, cid):
@@ -82,6 +83,7 @@ def cid_scores_admin(request, cid):
return cid_scores(request, cid_user.cid, cid_user.passcode)
def cid_scores(request, pk, passcode):
# exam = get_object_or_404(Exam, pk=pk)
@@ -95,11 +97,11 @@ def cid_scores(request, pk, passcode):
# questions = exam.exam_questions.all()
EXAM_ANSWER_MAP = {
"physics" : (PhysicsCidUserAnswer, PhysicsExam),
"anatomy" : (AnatomyCidUserAnswer, AnatomyExam),
"rapids" : (RapidsCidUserAnswer, RapidsExam),
"longs" : (LongsCidUserAnswer, LongsExam),
"sbas" : (SbasCidUserAnswer, SbasExam),
"physics": (PhysicsCidUserAnswer, PhysicsExam),
"anatomy": (AnatomyCidUserAnswer, AnatomyExam),
"rapids": (RapidsCidUserAnswer, RapidsExam),
"longs": (LongsCidUserAnswer, LongsExam),
"sbas": (SbasCidUserAnswer, SbasExam),
}
kwargs = {"exam_mode": True}
@@ -110,18 +112,17 @@ def cid_scores(request, pk, passcode):
exam_ids = exam_answers.values_list("exam").distinct()
exams.append((exam_type, Exam.objects.filter(id__in=exam_ids, **kwargs)))
available_exams = cid_user.get_cid_exams()
return render(
request,
"cid_scores.html",
{
#"physics_exams": physics_exams,
#"anatomy_exams": anatomy_exams,
#"rapid_exams": rapid_exams,
#"longs_exams": longs_exams,
#"sba_exams": sba_exams,
# "physics_exams": physics_exams,
# "anatomy_exams": anatomy_exams,
# "rapid_exams": rapid_exams,
# "longs_exams": longs_exams,
# "sba_exams": sba_exams,
"all_exams": exams,
"cid": cid,
"passcode": passcode,
@@ -140,13 +141,15 @@ def active_exams(request, cid=None, passcode=None):
if not cid_user or cid_user.passcode != passcode:
return JsonResponse({"status": "invalid"}, status=401)
anatomy_exams = AnatomyExamViews.active_exams(
anatomy_exams = GenericExamViews.active_exams(
request, False, cid=cid, passcode=passcode
)
rapid_exams = RapidExamViews.active_exams(
rapid_exams = GenericExamViews.active_exams(
request, False, cid=cid, passcode=passcode
)
long_exams = GenericExamViews.active_exams(
request, False, cid=cid, passcode=passcode
)
long_exams = LongExamViews.active_exams(request, False, cid=cid, passcode=passcode)
exams = []
exams.extend(anatomy_exams)
@@ -164,9 +167,9 @@ def active_exams(request, cid=None, passcode=None):
def active_exams_unbased(request):
anatomy_exams = AnatomyExamViews.active_exams(request, False, False)
rapid_exams = RapidExamViews.active_exams(request, False, False)
long_exams = LongExamViews.active_exams(request, False, False)
anatomy_exams = GenericExamViews.active_exams(request, False, False)
rapid_exams = GenericExamViews.active_exams(request, False, False)
long_exams = GenericExamViews.active_exams(request, False, False)
exams = []
exams.extend(anatomy_exams)
@@ -189,11 +192,11 @@ def exam_submit(request):
exam_type, exam_id = request.POST.get("eid").split("/")
if exam_type == "anatomy":
return AnatomyExamViews.postExamAnswers(request)
return GenericExamViews.postExamAnswers(request)
elif exam_type == "rapid":
return RapidExamViews.postExamAnswers(request)
return GenericExamViews.postExamAnswers(request)
elif exam_type == "long":
return LongExamViews.postExamAnswers(request)
return GenericExamViews.postExamAnswers(request)
return JsonResponse({"success": False, "error": "Invalid exam type"})
# postExamAnswers
+19 -17
View File
@@ -8,7 +8,7 @@ app_name = "rapids"
urlpatterns = [
# path('', views.question_list, name='question_list'),
path("", views.RapidExamViews.index, name="index"),
path("", views.GenericExamViews.index, name="index"),
path("author/<int:pk>/", views.GenericViews.author_detail, name="author_detail"),
path("author/", views.GenericViews.author_list, name="author_list"),
path("question_viewer", views.question_viewer, name="question_viewer"),
@@ -56,28 +56,28 @@ urlpatterns = [
"exam/<int:exam_pk>/<int:sk>/mark/review", views.mark_review, name="mark_review"
),
path(
"exam/<int:pk>/mark", views.RapidExamViews.mark_overview, name="mark_overview"
"exam/<int:pk>/mark", views.GenericExamViews.mark_overview, name="mark_overview"
),
# path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
path(
"exam/<int:pk>/question/<int:sk>/",
views.RapidExamViews.exam_question_detail,
views.GenericExamViews.exam_question_detail,
name="exam_question_detail",
),
path("exam/<int:pk>/", views.RapidExamViews.exam_overview, name="exam_overview"),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path(
"exam/<int:pk>/json_edit",
views.RapidExamViews.exam_json_edit,
views.GenericExamViews.exam_json_edit,
name="exam_json_edit",
),
path(
"exam/<int:pk>/scores",
views.RapidExamViews.exam_scores_cid,
views.GenericExamViews.exam_scores_cid,
name="exam_scores_cid",
),
path(
"exam/<int:pk>/scores/refresh",
views.RapidExamViews.exam_scores_refresh,
views.GenericExamViews.exam_scores_refresh,
# cache_page(60 * 1)(views.exam_scores_cid),
name="exam_scores_refresh",
),
@@ -88,38 +88,40 @@ urlpatterns = [
),
path(
"exam/<int:pk>/toggle_active",
views.RapidExamViews.exam_toggle_active,
views.GenericExamViews.exam_toggle_active,
name="exam_toggle_active",
),
path(
"exam/<int:pk>/toggle_results_published",
views.RapidExamViews.exam_toggle_results_published,
views.GenericExamViews.exam_toggle_results_published,
name="exam_toggle_results_published",
),
path(
"exam/submit", views.RapidExamViews.postExamAnswers, name="exam_answers_submit"
"exam/submit",
views.GenericExamViews.postExamAnswers,
name="exam_answers_submit",
),
path("exam/", views.RapidExamViews.exam_list, name="exam_list"),
path("exam/all", views.RapidExamViews.exam_list_all, name="exam_list_all"),
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
path("exam/json/", views.RapidExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.RapidExamViews.exam_json, name="exam_json"),
path("exam/json/", views.GenericExamViews.active_exams, name="active_exams"),
path("exam/json/<int:pk>", views.GenericExamViews.exam_json, name="exam_json"),
path(
"exam/json/<int:pk>/unbased",
views.RapidExamViews.exam_json_unbased,
views.GenericExamViews.exam_json_unbased,
name="exam_json_unbased",
),
path(
"exam/json/<int:pk>/<int:sk>/unbased",
views.RapidExamViews.exam_question_json_unbased,
views.GenericExamViews.exam_question_json_unbased,
name="exam_question_json_unbased",
),
path(
"exam/json/<int:pk>/recreate",
views.RapidExamViews.exam_json_recreate,
views.GenericExamViews.exam_json_recreate,
name="exam_json_recreate",
),
path("create/", views.RapidCreate.as_view(), name="rapid_create"),
+1 -1
View File
@@ -1047,7 +1047,7 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
success_url = reverse_lazy("rapids:rapid_view")
RapidExamViews = ExamViews(
GenericExamViews = ExamViews(
Exam, Rapid, CidUserAnswer, "rapids", "rapid", loadJsonAnswer
)
+16 -8
View File
@@ -7,17 +7,25 @@ app_name = "sbas"
urlpatterns = [
# path('', views.question_list, name='question_list'),
path("", views.SbasExamViews.index, name="index"),
path("", views.GenericExamViews.index, name="index"),
path("question/", views.QuestionView.as_view(), name="question_view"),
path("question/<int:pk>/", views.question_detail, name="question_detail"),
# path("question/create/", views.QuestionCreate.as_view(), name="anatomy_question_create"),
# path("question/<int:pk>/update", views.QuestionUpdate.as_view(), name="anatomy_question_update"),
# 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>/<int:sk>/<str:cid>/<str:passcode>/take", views.exam_take, name="exam_take"),
path(
"exam/<int:pk>/<int:sk>/<str:cid>/<str:passcode>/take",
views.exam_take,
name="exam_take",
),
path("exam/<int:pk>/start", views.exam_start, name="exam_start"),
path("exam/<int:pk>/<str:cid>/<str:passcode>/finish", views.exam_finish, name="exam_finish"),
path("exam/<int:pk>/", views.SbasExamViews.exam_overview, name="exam_overview"),
path(
"exam/<int:pk>/<str:cid>/<str:passcode>/finish",
views.exam_finish,
name="exam_finish",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path(
"exam/<int:pk>/scores",
cache_page(60 * 1)(views.exam_scores_cid),
@@ -30,16 +38,16 @@ urlpatterns = [
),
path(
"exam/<int:pk>/toggle_active",
views.SbasExamViews.exam_toggle_active,
views.GenericExamViews.exam_toggle_active,
name="exam_toggle_active",
),
path(
"exam/<int:pk>/toggle_results_published",
views.SbasExamViews.exam_toggle_results_published,
views.GenericExamViews.exam_toggle_results_published,
name="exam_toggle_results_published",
),
# path("exam/submit", views.PhysicsExamViews.postExamAnswers, name="exam_answers_submit"),
path("exam/", views.SbasExamViews.exam_list, name="exam_list"),
# path("exam/submit", views.GenericExamViews.postExamAnswers, name="exam_answers_submit"),
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
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>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
+29 -15
View File
@@ -47,6 +47,7 @@ from django.core.exceptions import PermissionDenied
from .tables import QuestionTable, UserAnswerTable
from .filters import QuestionFilter, UserAnswerFilter
class AuthorOrCheckerRequiredMixin(object):
def get_object(self, *args, **kwargs):
obj = super().get_object(*args, **kwargs)
@@ -56,6 +57,7 @@ class AuthorOrCheckerRequiredMixin(object):
raise PermissionDenied() # or Http404
return obj
def question_list(request):
questions = Question.objects.all()
return render(request, "sbas/question_list.html", {"questions": questions})
@@ -109,9 +111,17 @@ def exam_scores_cid(request, pk):
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
if not s:
# skip if no answer
user_answers_marks[cid].append((0,0,0,0,0))
user_answers_marks[cid].append((0, 0, 0, 0, 0))
user_answers[cid].append(("", "", "", "", ""))
by_question[q].append((("", 0),("", 0),("", 0),("", 0),("", 0),))
by_question[q].append(
(
("", 0),
("", 0),
("", 0),
("", 0),
("", 0),
)
)
continue
ans = s.get_answer()
@@ -191,7 +201,6 @@ def exam_scores_cid_user(request, pk, sk, passcode):
answers_marks = []
answers = []
view_all_results = False
if request.user.groups.filter(name="view_all_results").exists():
view_all_results = True
@@ -200,7 +209,6 @@ def exam_scores_cid_user(request, pk, sk, passcode):
# Get user answer
user_answer = q.cid_user_answers.filter(cid=cid).first()
if user_answer is None:
answer_score = 0
ans = ""
@@ -229,7 +237,7 @@ def exam_scores_cid_user(request, pk, sk, passcode):
{
"exam": exam,
"cid": cid,
"passcode" : passcode,
"passcode": passcode,
"questions": questions,
"answers": answers,
"answers_marks": answers_marks,
@@ -254,6 +262,7 @@ def exam_start(request, pk):
},
)
def exam_finish(request, pk, cid, passcode):
exam = get_object_or_404(Exam, pk=pk)
@@ -262,8 +271,7 @@ def exam_finish(request, pk, cid, passcode):
questions = exam.exam_questions.all()
answers = CidUserAnswer.objects.filter(
cid=cid, exam=exam)
answers = CidUserAnswer.objects.filter(cid=cid, exam=exam)
answer_question_map = {}
for ans in answers:
@@ -311,8 +319,7 @@ def exam_take(request, pk, sk, cid, passcode):
pos = exam.get_question_index(question)
answer = question.cid_user_answers.filter(
cid=cid, exam=exam).first()
answer = question.cid_user_answers.filter(cid=cid, exam=exam).first()
if request.method == "POST":
if answer:
@@ -336,7 +343,9 @@ def exam_take(request, pk, sk, cid, passcode):
elif "finish" in request.POST:
return redirect("sbas:exam_finish", **kwargs)
elif "goto" in request.POST:
return redirect("sbas:exam_take", sk=int(request.POST.get("goto")), **kwargs)
return redirect(
"sbas:exam_take", sk=int(request.POST.get("goto")), **kwargs
)
else:
form = CidUserAnswerForm(instance=answer)
@@ -351,7 +360,6 @@ def exam_take(request, pk, sk, cid, passcode):
if answer is not None:
saved_answer = answer.answer
return render(
request,
"sbas/exam_take.html",
@@ -373,7 +381,11 @@ def exam_take(request, pk, sk, cid, passcode):
def loadJsonAnswer(answer):
pass
SbasExamViews = ExamViews(Exam, Question, CidUserAnswer, "sbas", "sbas", loadJsonAnswer)
GenericExamViews = ExamViews(
Exam, Question, CidUserAnswer, "sbas", "sbas", loadJsonAnswer
)
class QuestionView(LoginRequiredMixin, SingleTableMixin, FilterView):
model = Question
@@ -382,6 +394,7 @@ class QuestionView(LoginRequiredMixin, SingleTableMixin, FilterView):
filterset_class = QuestionFilter
class UserAnswerView(LoginRequiredMixin, DetailView):
model = CidUserAnswer
@@ -399,8 +412,9 @@ class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
template_name = "user_answer_delete.html"
success_url = reverse_lazy("sbas:user_answer_table_view")
#@user_passes_test(lambda u: u.is_superuser)
#def user_answer_delete_multiple(request):
# @user_passes_test(lambda u: u.is_superuser)
# def user_answer_delete_multiple(request):
# if request.is_ajax():
# print(request.POST["answer_ids"])
# answer_ids = json.loads(request.POST["answer_ids"])
@@ -412,4 +426,4 @@ class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
# return JsonResponse({"status": "error"})
GenericViews = GenericViewBase("sbas", Question, CidUserAnswer, Exam)
GenericViews = GenericViewBase("sbas", Question, CidUserAnswer, Exam)