add user marknig pages
This commit is contained in:
@@ -106,6 +106,8 @@ urlpatterns = [
|
||||
path("cid/<int:cid>/", views.cid_scores_admin, name="cid_scores_admin"),
|
||||
path("user/scores", views.user_scores, name="user_scores"),
|
||||
path("user/scores/<int:user_id>", views.user_scores_admin, name="user_scores_admin"),
|
||||
path("user/marking", views.user_marking, name="user_marking"),
|
||||
path("user/marking/<str:exam_type>", views.user_marking_partial, name="user_marking_partial"),
|
||||
path("cid/", views.cid_selector, name="cid_selector"),
|
||||
path("cid/request_cid_details/", views.request_cid_details, name="request_cid_details"),
|
||||
# Global url that registers RTS compatible exams
|
||||
|
||||
@@ -12,6 +12,7 @@ from generic.views import (
|
||||
RedirectMixin,
|
||||
get_question_and_content_type,
|
||||
get_user_exams,
|
||||
get_exam_model_from_app_name,
|
||||
)
|
||||
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
@@ -266,6 +267,91 @@ def user_scores(request, user=None):
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def user_marking(request):
|
||||
"""Main page for user marking overview. Uses HTMX to fetch per-app partials."""
|
||||
apps = ["physics", "anatomy", "rapids", "shorts", "longs", "sbas"]
|
||||
return render(request, "rad/user_marking.html", {"apps": apps})
|
||||
|
||||
|
||||
@login_required
|
||||
def user_marking_partial(request, exam_type: str):
|
||||
"""Return an HTMX partial listing exams the user can mark for a given exam type.
|
||||
|
||||
Each exam is checked for whether it has any unmarked answers (using
|
||||
question.get_unmarked_user_answer_count when available).
|
||||
"""
|
||||
user = request.user
|
||||
|
||||
try:
|
||||
ExamModel = get_exam_model_from_app_name(exam_type)
|
||||
except Exception:
|
||||
return HttpResponse("Unknown exam type", status=400)
|
||||
|
||||
# Exams where user is an author or an authorised marker
|
||||
exams_qs = ExamModel.objects.filter(
|
||||
archive=False, exam_mode=True
|
||||
).filter(Q(author=user) | Q(markers=user)).prefetch_related("author", "markers")
|
||||
|
||||
exams_data = []
|
||||
for exam in exams_qs.order_by("name"):
|
||||
has_unmarked = False
|
||||
unmarked_count = 0
|
||||
# iterate questions and use their helper to count unmarked answers when available
|
||||
for q in exam.get_questions():
|
||||
count = 0
|
||||
# Prefer question-provided helper if present
|
||||
helper = getattr(q, "get_unmarked_user_answer_count", None)
|
||||
if callable(helper):
|
||||
try:
|
||||
count = helper(exam_pk=exam.pk, marker=user)
|
||||
except TypeError:
|
||||
count = helper(exam_pk=exam.pk)
|
||||
except Exception:
|
||||
count = 0
|
||||
else:
|
||||
# Fallback: inspect related answer manager if present
|
||||
rel_manager = None
|
||||
for rel_name in ("cid_user_answers", "user_answers", "answers", "useranswer_set"):
|
||||
if hasattr(q, rel_name):
|
||||
rel_manager = getattr(q, rel_name)
|
||||
break
|
||||
|
||||
if rel_manager is not None:
|
||||
try:
|
||||
ans_model = rel_manager.model
|
||||
# If the answer model has a `score` field, count answers that are unmarked
|
||||
field_names = [f.name for f in ans_model._meta.get_fields()]
|
||||
if "score" in field_names:
|
||||
# Try to detect an UNMARKED constant on the model
|
||||
unmarked_vals = [None, ""]
|
||||
model_score_const = getattr(ans_model, "ScoreOptions", None) or getattr(ans_model, "MarkOptions", None)
|
||||
if model_score_const is not None:
|
||||
# attempt to use any UNMARKED attribute
|
||||
unmarked_val = getattr(model_score_const, "UNMARKED", None)
|
||||
if unmarked_val is not None:
|
||||
unmarked_vals.append(unmarked_val)
|
||||
|
||||
count = rel_manager.filter(exam__id=exam.pk).filter(score__in=unmarked_vals).count()
|
||||
else:
|
||||
# No score field — likely auto-marked; treat as 0
|
||||
count = 0
|
||||
except Exception:
|
||||
count = 0
|
||||
|
||||
try:
|
||||
c = int(count)
|
||||
except Exception:
|
||||
c = 0
|
||||
if c:
|
||||
has_unmarked = True
|
||||
unmarked_count += c
|
||||
|
||||
exams_data.append({"exam": exam, "has_unmarked": has_unmarked, "unmarked_count": unmarked_count})
|
||||
|
||||
return render(request, "generic/partials/user_marking_exam_list.html", {"exams_data": exams_data, "exam_type": exam_type})
|
||||
|
||||
|
||||
def cid_scores(request, cid, passcode):
|
||||
# exam = get_object_or_404(Exam, pk=pk)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user