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

Merge branch 'optimize-get-objects' into 'master'

Optimize get objects

See merge request !381
parents 50f9a0ce 65921e17
No related branches found
No related tags found
1 merge request!381Optimize get objects
Pipeline #193575 failed
......@@ -25,63 +25,154 @@ class TimetableType(Enum):
class LessonEventQuerySet(RecurrencePolymorphicQuerySet):
"""Queryset with special query methods for lesson events."""
@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)
.union(LessonEvent.objects.filter(teachers=teacher).values_list("pk", flat=True))
)
return Q(pk__in=amended)
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, teachers=teacher
).values_list("amended_by__pk", flat=True)
return self.filter(Q(teachers=teacher) | Q(pk__in=amended)).distinct()
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, groups__members=person)
.values_list("amended_by__pk", flat=True)
.union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True))
)
return Q(pk__in=amended)
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(
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()
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, groups=group)
.values_list("amended_by__pk", flat=True)
.union(
LessonEvent.objects.filter(
amended_by__isnull=False, groups__parent_groups=group
).values_list("amended_by__pk", flat=True)
)
.union(LessonEvent.objects.filter(groups=group).values_list("pk", flat=True))
.union(
LessonEvent.objects.filter(groups__parent_groups=group).values_list("pk", flat=True)
)
)
return Q(pk__in=amended)
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(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()
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, rooms=room)
.values_list("amended_by__pk", flat=True)
.union(LessonEvent.objects.filter(rooms=room).values_list("pk", flat=True))
)
return Q(pk__in=amended)
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(
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()
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, course=course)
.values_list("amended_by__pk", flat=True)
.union(LessonEvent.objects.filter(course=course).values_list("pk", flat=True))
)
return Q(pk__in=amended)
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(amended_by__isnull=False, course=course).values_list(
"amended_by__pk", flat=True
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, teachers=person)
.values_list("amended_by__pk", flat=True)
.union(
LessonEvent.objects.filter(
amended_by__isnull=False, groups__members=person
).values_list("amended_by__pk", flat=True)
)
.union(LessonEvent.objects.filter(teachers=person).values_list("pk", flat=True))
.union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True))
)
return self.filter(Q(course=course) | Q(pk__in=amended)).distinct()
return Q(pk__in=amended)
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
teacher/participant/group owner/parent group owner,
including those amended.
"""
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()
amended = (
LessonEvent.objects.filter(amended_by__isnull=False, teachers=person)
.values_list("amended_by__pk", flat=True)
.union(
LessonEvent.objects.filter(
amended_by__isnull=False, groups__members=person
).values_list("amended_by__pk", flat=True)
)
.union(
LessonEvent.objects.filter(
amended_by__isnull=False, groups__owners=person
).values_list("amended_by__pk", flat=True)
)
.union(
LessonEvent.objects.filter(
amended_by__isnull=False, groups__parent_groups__owners=person
).values_list("amended_by__pk", flat=True)
)
.union(LessonEvent.objects.filter(teachers=person).values_list("pk", flat=True))
.union(LessonEvent.objects.filter(groups__members=person).values_list("pk", flat=True))
.union(LessonEvent.objects.filter(groups__owners=person).values_list("pk", flat=True))
.union(
LessonEvent.objects.filter(groups__parent_groups__owners=person).values_list(
"pk", flat=True
)
)
)
return Q(pk__in=amended)
def related_to_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
"""Get all lesson events a certain person is allowed to see.
......@@ -90,36 +181,34 @@ class LessonEventQuerySet(RecurrencePolymorphicQuerySet):
teacher/participant/group owner/parent group owner,
including those amended.
"""
from .models import LessonEvent
return self.filter(self.related_to_person_q(person)).distinct()
amended = LessonEvent.objects.filter(
Q(amended_by__isnull=False)
& (
Q(teachers=person)
| Q(groups__members=person)
| Q(groups__owners=person)
| Q(groups__parent_groups__owners=person)
)
).values_list("amended_by__pk", flat=True)
return self.filter(
Q(teachers=person)
| Q(groups__members=person)
| Q(groups__owners=person)
| Q(groups__parent_groups__owners=person)
| Q(pk__in=amended)
).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
......@@ -407,23 +406,22 @@ class LessonEvent(CalendarEvent):
params: dict[str, any] | None = None,
no_effect: bool = False,
**kwargs,
) -> Iterable:
) -> QuerySet:
"""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 cls.objects.none()
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,44 @@ 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)
if "own" in params:
return objs
if request:
return objs.for_person(request.user.person)
q = q & LessonEventQuerySet.for_course_q(obj_id)
elif request:
q = q & LessonEventQuerySet.for_person_q(request.user.person)
objs = super().get_objects(
request,
params,
start_qs=cls.objects.not_instance_of(SupervisionEvent),
additional_filter=q,
select_related=["subject", "course"],
prefetch_related=["groups", "teachers", "rooms", "groups__members"],
**kwargs,
)
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