From 4717d721213b7ad2a5aaac9a5ae230238737a5b7 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Sun, 23 Jun 2024 17:37:31 +0200 Subject: [PATCH] Optimize documentation queries --- aleksis/apps/alsijil/models.py | 26 ++++++++++++++------ aleksis/apps/alsijil/schema/__init__.py | 8 +++++- aleksis/apps/alsijil/schema/documentation.py | 3 +-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index 8dd46a5a8..6be1734a1 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -530,6 +530,8 @@ class Documentation(CalendarEvent): @classmethod def get_documentations_for_events( cls, + datetime_start: datetime, + datetime_end: datetime, events: list, incomplete: Optional[bool] = False, ) -> tuple: @@ -539,18 +541,28 @@ class Documentation(CalendarEvent): """ docs = [] dummies = [] + + # Prefetch existing documentations to speed things up + existing_documentations = Documentation.objects.filter( + datetime_start__lte=datetime_end, + datetime_end__gte=datetime_start, + amends__in=[e["REFERENCE_OBJECT"] for e in events], + ).prefetch_related("participations") + for event in events: if incomplete and event["STATUS"] == "CANCELLED": continue event_reference_obj = event["REFERENCE_OBJECT"] - existing_documentations = event_reference_obj.amended_by.filter( - datetime_start=event["DTSTART"].dt, - datetime_end=event["DTEND"].dt, + existing_documentations_event = filter( + lambda d: ( + d.datetime_start == event["DTSTART"].dt and d.datetime_end == event["DTEND"].dt + ), + existing_documentations, ) - if existing_documentations.exists(): - doc = existing_documentations.first() + doc = next(existing_documentations_event, None) + if doc: if incomplete and doc.topic: continue docs.append(doc) @@ -579,7 +591,7 @@ class Documentation(CalendarEvent): ) ) - return (docs, dummies) + return docs, dummies @classmethod def get_documentations_for_person( @@ -606,7 +618,7 @@ class Documentation(CalendarEvent): with_reference_object=True, ) - return Documentation.get_documentations_for_events(events, incomplete) + return Documentation.get_documentations_for_events(start, end, events, incomplete) @classmethod def parse_dummy( diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 2634a297d..ec8a9b025 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -11,6 +11,7 @@ from aleksis.apps.cursus.schema import CourseType from aleksis.core.models import Group, Person from aleksis.core.schema.base import FilterOrderList from aleksis.core.schema.group import GroupType +from aleksis.core.schema.person import PersonType from aleksis.core.util.core_helpers import has_person from ..models import Documentation @@ -112,7 +113,12 @@ class Query(graphene.ObjectType): ) # Lookup or create documentations and return them all. - docs, dummies = Documentation.get_documentations_for_events(events, incomplete) + docs, dummies = Documentation.get_documentations_for_events( + datetime.combine(date_start, datetime.min.time()), + datetime.combine(date_end, datetime.max.time()), + events, + incomplete, + ) return docs + dummies @staticmethod diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py index 63aecfdfc..39eed04a4 100644 --- a/aleksis/apps/alsijil/schema/documentation.py +++ b/aleksis/apps/alsijil/schema/documentation.py @@ -34,7 +34,6 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp "date_start", "date_end", "teachers", - "participations", ) filter_fields = { "id": ["exact", "lte", "gte"], @@ -78,7 +77,7 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp # A dummy documentation will not have any participations if str(root.pk).startswith("DUMMY") or not hasattr(root, "participations"): return [] - return root.participations.select_related("absence_reason", "base_absence").all() + return root.participations.all() class DocumentationInputType(graphene.InputObjectType): -- GitLab