diff --git a/website/education/models.py b/website/education/models.py index ddfbc73bb..47a3ef668 100644 --- a/website/education/models.py +++ b/website/education/models.py @@ -1,9 +1,13 @@ import datetime from django.db import models +from django.db.models import Count, Q from django.urls import reverse from django.utils.translation import gettext_lazy as _ +from queryable_properties.managers import QueryablePropertiesManager +from queryable_properties.properties import AggregateProperty + from members.models import Member from utils.snippets import datetime_to_lectureyear @@ -29,6 +33,8 @@ class Meta: class Course(models.Model): """Describes a course.""" + objects = QueryablePropertiesManager() + name = models.CharField(max_length=255) categories = models.ManyToManyField( @@ -52,6 +58,11 @@ def __str__(self): def get_absolute_url(self): return reverse("education:course", args=[str(self.pk)]) + summary_count = AggregateProperty( + Count("summary", filter=Q(summary__accepted=True)) + ) + exam_count = AggregateProperty(Count("exam", filter=Q(exam__accepted=True))) + class Meta: ordering = ["-pk"] verbose_name = _("course") diff --git a/website/education/views.py b/website/education/views.py index 685c24a99..000c8b28c 100644 --- a/website/education/views.py +++ b/website/education/views.py @@ -12,6 +12,8 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, ListView, TemplateView +from queryable_properties.utils import prefetch_queryable_properties + from members.decorators import membership_required from utils.media.services import get_media_url @@ -23,9 +25,17 @@ class CourseIndexView(ListView): """Render an overview of the courses.""" - queryset = Course.objects.filter(until=None).prefetch_related( - "categories", "old_courses" - ) + def get_queryset(self): + queryset = ( + Course.objects.filter(until=None) + .prefetch_related("categories", "old_courses") + .select_properties("summary_count", "exam_count") + .order_by("name") + ) + prefetch_queryable_properties(queryset, "old_courses__summary_count") + prefetch_queryable_properties(queryset, "old_courses__exam_count") + return queryset + template_name = "education/courses.html" def get_ordering(self) -> str: @@ -42,12 +52,11 @@ def get_context_data(self, **kwargs) -> dict: "categories": x.categories.all(), "document_count": sum( [ - x.summary_set.filter(accepted=True).count(), - x.exam_set.filter(accepted=True).count(), + x.summary_count, + x.exam_count, ] + [ - c.summary_set.filter(accepted=True).count() - + c.exam_set.filter(accepted=True).count() + c.summary_count + c.exam_count for c in x.old_courses.all() ] ),