Skip to content
Snippets Groups Projects
Verified Commit 9f67b1e1 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Prefilter lesson events before calculating occurrences

parent 2ddacae0
No related branches found
No related tags found
1 merge request!381Optimize get objects
Pipeline #193464 passed
......@@ -25,65 +25,92 @@ class TimetableType(Enum):
class LessonEventQuerySet(RecurrencePolymorphicQuerySet):
"""Queryset with special query methods for lesson events."""
def for_teacher(self, teacher: Union[int, Person]) -> "LessonEventQuerySet":
@staticmethod
def for_teacher_q(teacher: Union[int, Person]) -> Q:
"""Get all lesson events for a certain person as teacher (including amends)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(
amended_by__isnull=False, teachers=teacher
).values_list("amended_by__pk", flat=True)
return self.filter(Q(teachers=teacher) | Q(pk__in=amended)).distinct()
return Q(teachers=teacher) | Q(pk__in=amended)
def for_participant(self, person: Union[int, Person]) -> "LessonEventQuerySet":
def for_teacher(self, teacher: Union[int, Person]) -> "LessonEventQuerySet":
"""Get all lesson events for a certain person as teacher (including amends)."""
return self.filter(self.for_teacher_q(teacher)).distinct()
@staticmethod
def for_participant_q(person: Union[int, Person]) -> Q:
"""Get all lesson events the person participates in (including amends)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(
amended_by__isnull=False, groups__members=person
).values_list("amended_by__pk", flat=True)
return self.filter(Q(groups__members=person) | Q(pk__in=amended)).distinct()
return Q(groups__members=person) | Q(pk__in=amended)
def for_group(self, group: Union[int, Group]) -> "LessonEventQuerySet":
def for_participant(self, person: Union[int, Person]) -> "LessonEventQuerySet":
"""Get all lesson events the person participates in (including amends)."""
return self.filter(self.for_participant_q(person)).distinct()
@staticmethod
def for_group_q(group: Union[int, Group]) -> Q:
"""Get all lesson events for a certain group (including amends/as parent group)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(
Q(amended_by__isnull=False) & (Q(groups=group) | Q(groups__parent_groups=group))
).values_list("amended_by__pk", flat=True)
return self.filter(
Q(groups=group) | Q(groups__parent_groups=group) | Q(pk__in=amended)
).distinct()
return Q(groups=group) | Q(groups__parent_groups=group) | Q(pk__in=amended)
def for_room(self, room: Union[int, Room]) -> "LessonEventQuerySet":
def for_group(self, group: Union[int, Group]) -> "LessonEventQuerySet":
"""Get all lesson events for a certain group (including amends/as parent group)."""
return self.filter(self.for_group_q(group)).distinct()
@staticmethod
def for_room_q(room: Union[int, Room]) -> Q:
"""Get all lesson events for a certain room (including amends)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(
Q(amended_by__isnull=False) & (Q(rooms=room))
).values_list("amended_by__pk", flat=True)
return self.filter(Q(rooms=room) | Q(pk__in=amended)).distinct()
return Q(rooms=room) | Q(pk__in=amended)
def for_course(self, course: Union[int, Course]) -> "LessonEventQuerySet":
def for_room(self, room: Union[int, Room]) -> "LessonEventQuerySet":
"""Get all lesson events for a certain room (including amends)."""
return self.filter(self.for_room_q(room)).distinct()
@staticmethod
def for_course_q(course: Union[int, Course]) -> Q:
"""Get all lesson events for a certain course (including amends)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(amended_by__isnull=False, course=course).values_list(
"amended_by__pk", flat=True
)
return self.filter(Q(course=course) | Q(pk__in=amended)).distinct()
return Q(course=course) | Q(pk__in=amended)
def for_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
def for_course(self, course: Union[int, Course]) -> "LessonEventQuerySet":
"""Get all lesson events for a certain course (including amends)."""
return self.filter(self.for_course_q(course)).distinct()
@staticmethod
def for_person_q(person: Union[int, Person]) -> Q:
"""Get all lesson events for a certain person (as teacher/participant, including amends)."""
from .models import LessonEvent
amended = LessonEvent.objects.filter(
Q(amended_by__isnull=False) & (Q(teachers=person) | Q(groups__members=person))
).values_list("amended_by__pk", flat=True)
return self.filter(
Q(teachers=person) | Q(groups__members=person) | Q(pk__in=amended)
).distinct()
return Q(teachers=person) | Q(groups__members=person) | Q(pk__in=amended)
def related_to_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
def for_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
"""Get all lesson events for a certain person (as teacher/participant, including amends)."""
return self.filter(self.for_person_q(person)).distinct()
@staticmethod
def related_to_person_q(person: Union[int, Person]) -> Q:
"""Get all lesson events a certain person is allowed to see.
This includes all lesson events the person is assigned to as
......@@ -101,25 +128,49 @@ class LessonEventQuerySet(RecurrencePolymorphicQuerySet):
| Q(groups__parent_groups__owners=person)
)
).values_list("amended_by__pk", flat=True)
return self.filter(
return (
Q(teachers=person)
| Q(groups__members=person)
| Q(groups__owners=person)
| Q(groups__parent_groups__owners=person)
| Q(pk__in=amended)
).distinct()
)
def related_to_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
"""Get all lesson events a certain person is allowed to see.
This includes all lesson events the person is assigned to as
teacher/participant/group owner/parent group owner,
including those amended.
"""
return self.filter(self.related_to_person_q(person)).distinct()
@staticmethod
def not_amended_q() -> Q:
"""Get all lesson events that are not amended."""
return Q(amended_by__isnull=True)
def not_amended(self) -> "LessonEventQuerySet":
"""Get all lesson events that are not amended."""
return self.filter(amended_by__isnull=True)
return self.filter(self.not_amended_q())
@staticmethod
def not_amending_q() -> Q:
"""Get all lesson events that are not amending other events."""
return Q(amends__isnull=True)
def not_amending(self) -> "LessonEventQuerySet":
"""Get all lesson events that are not amending other events."""
return self.filter(amends__isnull=True)
return self.filter(self.not_amending_q())
@staticmethod
def amending_q() -> Q:
"""Get all lesson events that are amending other events."""
return Q(amends__isnull=False)
def amending(self) -> "LessonEventQuerySet":
"""Get all lesson events that are amending other events."""
return self.filter(amends__isnull=False)
return self.filter(self.amending_q())
class SupervisionEventQuerySet(LessonEventQuerySet):
......
......@@ -7,10 +7,9 @@ from datetime import date
from typing import Any
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.core.validators import MinValueValidator
from django.db import models
from django.db.models import QuerySet
from django.db.models import Q, QuerySet
from django.dispatch import receiver
from django.http import HttpRequest
from django.template.loader import render_to_string
......@@ -411,19 +410,18 @@ class LessonEvent(CalendarEvent):
"""Return all objects that should be included in the calendar."""
if no_effect:
return super().get_objects(request, params, **kwargs)
objs = (
super()
.get_objects(request, params, **kwargs)
.not_instance_of(SupervisionEvent)
.select_related("subject", "course")
.prefetch_related("groups", "teachers", "rooms", "groups__members")
)
if request and not has_person(request.user):
raise PermissionDenied()
return []
q = Q()
if params:
obj_id = int(params.get("id", 0))
try:
obj_id = int(params.get("id", 0))
except ValueError:
obj_id = None
type_ = params.get("type", None)
not_amended = params.get("not_amended", False)
not_amending = params.get("not_amending", False)
......@@ -431,36 +429,43 @@ class LessonEvent(CalendarEvent):
own = params.get("own", False)
if not_amended:
objs = objs.not_amended()
q = q & LessonEventQuerySet.not_amended_q()
if not_amending:
objs = objs.not_amending()
q = q & LessonEventQuerySet.not_amending_q()
if amending:
objs = objs.amending()
q = q & LessonEventQuerySet.amending_q()
if request and "own" in params:
if own:
objs = objs.for_person(request.user.person)
q = q & LessonEventQuerySet.for_person_q(request.user.person)
else:
objs = objs.related_to_person(request.user.person)
q = q & LessonEventQuerySet.related_to_person_q(request.user.person)
if type_ and obj_id:
if type_ == "TEACHER":
return objs.for_teacher(obj_id)
q = q & LessonEventQuerySet.for_teacher_q(obj_id)
elif type_ == "PARTICIPANT":
return objs.for_participant(obj_id)
q = q & LessonEventQuerySet.for_participant_q(obj_id)
elif type_ == "GROUP":
return objs.for_group(obj_id)
q = q & LessonEventQuerySet.for_group_q(obj_id)
elif type_ == "ROOM":
return objs.for_room(obj_id)
q = q & LessonEventQuerySet.for_room_q(obj_id)
elif type_ == "COURSE":
return objs.for_course(obj_id)
q = q & LessonEventQuerySet.for_course_q(obj_id)
if "own" in params:
return objs
if request:
return objs.for_person(request.user.person)
elif request:
q = q & LessonEventQuerySet.for_person_q(request.user.person)
objs = (
super()
.get_objects(request, params, additional_filter=q, **kwargs)
.not_instance_of(SupervisionEvent)
.filter(q)
.select_related("subject", "course")
.prefetch_related("groups", "teachers", "rooms", "groups__members")
)
return objs
class Meta:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment