diff --git a/aleksis/apps/chronos/managers.py b/aleksis/apps/chronos/managers.py
index d52c750d5575910fa50299628ab6735ddb7d142b..f02daf466b083e10b7af26dc77df8a0f3042b33c 100644
--- a/aleksis/apps/chronos/managers.py
+++ b/aleksis/apps/chronos/managers.py
@@ -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):
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index d2ca3cdd4c77e26f716c3a51af883fe1eb16cc75..43b6c9b57924a4c9f9c5f4001ab34fa31e5791aa 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -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: