Enhance ExamCollectionDetail queryset to prefetch related exams and annotate candidate counts for improved performance in templates

This commit is contained in:
Ross
2025-12-29 12:18:31 +00:00
parent 32c4305754
commit 768e1bf8c5
2 changed files with 80 additions and 3 deletions
+62
View File
@@ -5876,6 +5876,68 @@ class ExamCollectionList(LoginRequiredMixin, ListView):
class ExamCollectionDetail(AuthorRequiredMixin, DetailView):
model = ExamCollection
def get_queryset(self):
# Prefetch related exam sets and annotate candidate counts to avoid per-exam DB hits in templates
qs = super().get_queryset()
try:
from anatomy.models import Exam as AnatomyExam
from longs.models import Exam as LongsExam
from rapids.models import Exam as RapidsExam
from shorts.models import Exam as ShortsExam
from physics.models import Exam as PhysicsExam
from sbas.models import Exam as SbasExam
qs = qs.prefetch_related(
Prefetch(
'anatomy_exams',
queryset=AnatomyExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
Prefetch(
'longs_exams',
queryset=LongsExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
Prefetch(
'rapids_exams',
queryset=RapidsExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
Prefetch(
'shorts_exams',
queryset=ShortsExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
Prefetch(
'physics_exams',
queryset=PhysicsExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
Prefetch(
'sbas_exams',
queryset=SbasExam.objects.annotate(
valid_cid_users_count=Count('valid_cid_users'),
valid_user_users_count=Count('valid_user_users'),
).prefetch_related('author'),
),
'author',
)
except Exception:
# If any app is missing or import fails, fall back to default queryset
pass
return qs
class ExamCollectionEdit(AuthorRequiredMixin, UpdateView):
model = ExamCollection
+18 -3
View File
@@ -17,9 +17,24 @@
{% if app_name == 'anatomy' %}<a href="{% url 'anatomy:mark2_overview' pk=exam.pk %}" class="flex-col-half">Mark2</a>{% endif %}
{% endif %}
<span class="flex-col">
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a> <span class="candidate-counts">[<span title="Number of active CID users">
{{exam.valid_cid_users.count}}
</span> / <span title="Number of active User users">{{exam.valid_user_users.count}}]</span></span>
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a>
<span class="candidate-counts">[
<span title="Number of active CID users">
{% if exam.valid_cid_users_count is not None %}
{{ exam.valid_cid_users_count }}
{% else %}
{{ exam.valid_cid_users.count }}
{% endif %}
</span>
/
<span title="Number of active User users">
{% if exam.valid_user_users_count is not None %}
{{ exam.valid_user_users_count }}
{% else %}
{{ exam.valid_user_users.count }}
{% endif %}
]</span>
</span>
</span>
<a href="{% url app_name|add:':exam_scores_all' pk=exam.pk %}" class="flex-col-half">Scores</a>
<input type="checkbox" id="active-{{exam.pk}}" class="exam-active-switch" data-posturl="{% url app_name|add:':exam_toggle_active' pk=exam.pk %}" {% if exam.active %}checked{% endif %}>