Optimize question loading and user answer retrieval in ExamViews to reduce database queries

This commit is contained in:
Ross
2025-12-29 12:09:18 +00:00
parent b9d86a7639
commit 3e1cb4b54f
+15 -14
View File
@@ -3436,29 +3436,30 @@ class ExamViews(View, LoginRequiredMixin):
if user is None:
user = request.user
questions = (
exam.get_questions()
) # .prefetch_related("cid_user_answers", "answers")
# Load questions; prefetch 'answers' for apps that use them to avoid repeated DB hits
questions_qs = exam.get_questions()
if self.app_name not in ("physics",):
questions_qs = questions_qs.prefetch_related("answers")
# cid_user_answers = list(UserAnswer.objects.filter(cid=cid, exam__id=pk).prefetch_related("question"))
# Materialize questions list for iteration
questions = list(questions_qs)
# cid_user_answers_q_map = {}
# Fetch all relevant UserAnswer objects up-front to avoid per-question queries
if cid is not None:
user_answers_qs = self.UserAnswer.objects.filter(cid=cid, exam__id=pk).select_related("question")
else:
user_answers_qs = self.UserAnswer.objects.filter(user=user, exam__id=pk).select_related("question")
# for ans in cid_user_answers:
# cid_user_answers_q_map[ans.question] = ans
# Map question_id -> UserAnswer for O(1) lookup
user_answers_map = {ua.question_id: ua for ua in user_answers_qs}
answers_and_marks = []
answers_marks = []
answers = []
for q in questions:
# Get user answer
if cid is not None:
user_answer = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
else:
user_answer = q.cid_user_answers.filter(
user=request.user, exam__id=pk
).first()
# Get user answer from the in-memory map (avoids N+1 queries)
user_answer = user_answers_map.get(q.pk)
# user_answer = cid_user_answers_q_map[q]
feedback = None