Add user answer viewing and compaction

This commit is contained in:
Ross
2026-07-06 09:07:48 +01:00
parent 5ce4a67b31
commit 5a2baaeab8
16 changed files with 370 additions and 4 deletions
+130
View File
@@ -3897,6 +3897,7 @@ class ExamViews(View, LoginRequiredMixin):
"total_score": total_score,
"max_score": max_score,
"answers_and_marks": answers_and_marks,
"user_answers_map": user_answers_map,
"view_all_results": view_all_results,
"supervisor": supervisor,
#"cid_user_exam": cid_user_exam,
@@ -5238,6 +5239,135 @@ def import_exam_answers(request):
del request.session["pending_import_data"]
return render(request, "generic/import_exam_answers.html")
def compact_history_for_object(obj):
"""
Helper function to delete all historical revisions for a registered object,
leaving only the most recent version.
"""
from reversion.models import Version
versions = Version.objects.get_for_object(obj).order_by("-revision__date_created")
count = versions.count()
if count > 1:
# Keep the latest version, delete older versions and their revisions
recent_version = versions[0]
old_versions = list(versions[1:])
for v in old_versions:
revision = v.revision
v.delete()
if not revision.version_set.exists():
revision.delete()
return count - 1
return 0
@login_required
def view_answer_history(request, app_name, model_name, pk):
"""
View to display the revision history for a user/candidate answer,
and compact history (individual and bulk).
"""
from django.contrib import messages
from django.apps import apps
from reversion.models import Version
try:
Model = apps.get_model(app_name, model_name)
except LookupError:
raise Http404("Model not found")
answer = get_object_or_404(Model, pk=pk)
# Check permissions
can_view = (
request.user.is_staff
or request.user.is_superuser
or request.user.groups.filter(name__in=[
"cid_user_manager", "anatomy_checker", "rapid_checker", "long_checker"
]).exists()
)
exam = getattr(answer, "exam", None)
collection = None
if hasattr(answer, "question") and hasattr(answer.question, "collection"):
collection = answer.question.collection
if not can_view:
if exam and hasattr(exam, "author") and request.user in exam.author.all():
can_view = True
if collection and hasattr(collection, "author") and request.user in collection.author.all():
can_view = True
if not can_view:
raise PermissionDenied("You do not have permission to view this answer's history")
if request.method == "POST":
action = request.POST.get("action")
if action == "compact_single":
compacted = compact_history_for_object(answer)
messages.success(request, f"Compacted single answer history. Removed {compacted} old revisions.")
return HttpResponseRedirect(request.path)
elif action == "compact_bulk":
compacted_total = 0
if exam:
answers_qs = Model.objects.filter(exam=exam)
for ans in answers_qs:
compacted_total += compact_history_for_object(ans)
messages.success(request, f"Bulk compacted history for all answers in Exam '{exam}'. Removed {compacted_total} old revisions.")
elif collection:
from atlas.models import CidReportAnswer, UserReportAnswer
cids_qs = CidReportAnswer.objects.filter(question__collection=collection)
users_qs = UserReportAnswer.objects.filter(question__collection=collection)
for ans in cids_qs:
compacted_total += compact_history_for_object(ans)
for ans in users_qs:
compacted_total += compact_history_for_object(ans)
messages.success(request, f"Bulk compacted history for all answers in Case Collection '{collection}'. Removed {compacted_total} old revisions.")
return HttpResponseRedirect(request.path)
# GET request
versions = Version.objects.get_for_object(answer).select_related("revision__user").order_by("-revision__date_created")
history_data = []
for v in versions:
fields = v.field_dict
# Format answer contents nicely based on model/app
ans_text = fields.get("answer", "")
if not ans_text:
if model_name.lower() == "useranswer" and app_name.lower() == "longs":
ans_text = (
f"Observations: {fields.get('answer_observations', '')}\n"
f"Interpretation: {fields.get('answer_interpretation', '')}\n"
f"Diagnosis: {fields.get('answer_principle_diagnosis', '')}\n"
f"Differential: {fields.get('answer_differential_diagnosis', '')}\n"
f"Management: {fields.get('answer_management', '')}"
)
elif model_name.lower() == "useranswer" and app_name.lower() == "physics":
ans_text = f"A: {fields.get('a')}, B: {fields.get('b')}, C: {fields.get('c')}, D: {fields.get('d')}, E: {fields.get('e')}"
history_data.append({
"revision_id": v.revision_id,
"date": v.revision.date_created,
"user": v.revision.user,
"answer_text": ans_text,
"score": fields.get("score", ""),
"comment": v.revision.comment,
})
context = {
"answer": answer,
"history": history_data,
"exam": exam,
"collection": collection,
"app_name": app_name,
"model_name": model_name,
}
return render(request, "generic/answer_history.html", context)
@user_is_cid_user_manager
def user_group_add_by_email_user(request, group_id):
if request.htmx: