diff --git a/aleksis/apps/chronos/managers.py b/aleksis/apps/chronos/managers.py
index d537dd457e344b43de60f19e1063be9bfc1dfc2e..79bd043f4b28300ca5d6df961d43e820ae92a40b 100644
--- a/aleksis/apps/chronos/managers.py
+++ b/aleksis/apps/chronos/managers.py
@@ -9,6 +9,7 @@ from django.db.models.fields import DateField
 from django.db.models.functions import Concat
 
 from calendarweek import CalendarWeek
+from polymorphic.managers import PolymorphicQuerySet
 
 from aleksis.apps.chronos.util.date import week_weekday_from_date, week_weekday_to_date
 from aleksis.core.managers import DateRangeQuerySetMixin, SchoolTermRelatedQuerySet
@@ -861,14 +862,14 @@ class RoomPropertiesMixin:
         return sep.join([room.short_name for room in self.get_rooms()])
 
 
-class LessonEventQuerySet(QuerySet):
+class LessonEventQuerySet(PolymorphicQuerySet):
     """Queryset with special query methods for lesson events."""
 
     def for_teacher(self, teacher: Union[int, Person]):
-        amended = objs.filter(Q(amended_by__isnull=False) & (Q(teachers=teacher))).values_list(
+        amended = self.filter(Q(amended_by__isnull=False) & (Q(teachers=teacher))).values_list(
             "amended_by__pk", flat=True
         )
-        return objs.filter(Q(teachers=teacher) | Q(pk__in=amended)).distinct()
+        return self.filter(Q(teachers=teacher) | Q(pk__in=amended)).distinct()
 
     def for_group(self, group: Union[int, Group]):
         amended = self.filter(
diff --git a/aleksis/apps/chronos/migrations/0001_initial.py b/aleksis/apps/chronos/migrations/0001_initial.py
index 883b25bbf97f4bb0660e787d0a787b754b5efec4..023ea06eb613a00e8b24b0f90046d92ae906a126 100644
--- a/aleksis/apps/chronos/migrations/0001_initial.py
+++ b/aleksis/apps/chronos/migrations/0001_initial.py
@@ -1,13 +1,14 @@
 # Generated by Django 3.0.5 on 2020-05-04 14:16
 
 import django.contrib.postgres.fields.jsonb
-import django.contrib.sites.managers
 import django.db.models.deletion
 from django.db import migrations, models
 
 import calendarweek.calendarweek
 import colorfield.fields
 
+import aleksis.core.managers
+
 import aleksis.apps.chronos.managers
 
 
@@ -49,7 +50,7 @@ class Migration(migrations.Migration):
                 ),
                 "managed": False,
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="Break",
@@ -80,7 +81,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Breaks",
                 "ordering": ["after_period"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="Lesson",
@@ -119,7 +120,7 @@ class Migration(migrations.Migration):
                 aleksis.apps.chronos.managers.GroupPropertiesMixin,
                 aleksis.apps.chronos.managers.TeacherPropertiesMixin,
             ),
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="LessonPeriod",
@@ -251,7 +252,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Time periods",
                 "ordering": ["weekday", "period"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="SupervisionSubstitution",
@@ -353,7 +354,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Supervision areas",
                 "ordering": ["name"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.AddField(
             model_name="supervision",
@@ -458,7 +459,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Subjects",
                 "ordering": ["name", "short_name"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="Room",
@@ -500,7 +501,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Rooms",
                 "ordering": ["name", "short_name"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="LessonSubstitution",
@@ -871,7 +872,7 @@ class Migration(migrations.Migration):
                 "verbose_name_plural": "Exams",
                 "ordering": ["date"],
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="Event",
@@ -1032,7 +1033,7 @@ class Migration(migrations.Migration):
                 "verbose_name": "Absence reason",
                 "verbose_name_plural": "Absence reasons",
             },
-            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+            managers=[("objects", aleksis.core.managers.AlekSISBaseManager()),],
         ),
         migrations.CreateModel(
             name="Absence",
diff --git a/aleksis/apps/chronos/migrations/0015_add_managed_by_app_label.py b/aleksis/apps/chronos/migrations/0015_add_managed_by_app_label.py
new file mode 100644
index 0000000000000000000000000000000000000000..d4906fcd7eefb3fffd36136c75fa8d4feee76cc8
--- /dev/null
+++ b/aleksis/apps/chronos/migrations/0015_add_managed_by_app_label.py
@@ -0,0 +1,96 @@
+# Generated by Django 4.2.3 on 2023-07-27 13:35
+
+import aleksis.core.managers
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('sites', '0002_alter_domain_unique'),
+        ('chronos', '0014_lessonevent'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='absence',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='absencereason',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='break',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='event',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='exam',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='extralesson',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='holiday',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='lesson',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='lessonperiod',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='lessonsubstitution',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='subject',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='supervision',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='supervisionarea',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='supervisionsubstitution',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='timeperiod',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+        migrations.AddField(
+            model_name='validityrange',
+            name='managed_by_app_label',
+            field=models.CharField(blank=True, editable=False, max_length=255, verbose_name='App label of app responsible for managing this instance'),
+        ),
+    ]
diff --git a/aleksis/apps/chronos/migrations/0015_managed_by_site.py b/aleksis/apps/chronos/migrations/0015_managed_by_site.py
deleted file mode 100644
index 001528f86f0b981003a27b32558df0f25ea5f1e3..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/migrations/0015_managed_by_site.py
+++ /dev/null
@@ -1,390 +0,0 @@
-# Generated by Django 4.2.3 on 2023-07-31 08:21
-
-import aleksis.core.managers
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ("sites", "0002_alter_domain_unique"),
-        ("chronos", "0014_lessonevent"),
-    ]
-
-    operations = [
-        migrations.AlterModelManagers(
-            name="absencereason",
-            managers=[
-                ("objects", aleksis.core.managers.AlekSISBaseManager()),
-            ],
-        ),
-        migrations.AlterModelManagers(
-            name="automaticplan",
-            managers=[],
-        ),
-        migrations.AlterModelManagers(
-            name="subject",
-            managers=[
-                ("objects", aleksis.core.managers.AlekSISBaseManager()),
-            ],
-        ),
-        migrations.AlterModelManagers(
-            name="supervisionarea",
-            managers=[
-                ("objects", aleksis.core.managers.AlekSISBaseManager()),
-            ],
-        ),
-        migrations.AddField(
-            model_name="absence",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="absencereason",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="break",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="event",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="exam",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="extralesson",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="holiday",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="lesson",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="lessonperiod",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="lessonsubstitution",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="subject",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="supervision",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="supervisionarea",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="supervisionsubstitution",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="timeperiod",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AddField(
-            model_name="validityrange",
-            name="managed_by_app_label",
-            field=models.CharField(
-                blank=True,
-                editable=False,
-                max_length=255,
-                verbose_name="App label of app responsible for managing this instance",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="absence",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="absencereason",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="break",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="event",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="exam",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="extralesson",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="holiday",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="lesson",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="lessonperiod",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="lessonsubstitution",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="subject",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="supervision",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="supervisionarea",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="supervisionsubstitution",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="timeperiod",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="timeperiod",
-            name="weekday",
-            field=models.PositiveSmallIntegerField(
-                choices=[
-                    (0, "Monday"),
-                    (1, "Tuesday"),
-                    (2, "Wednesday"),
-                    (3, "Thursday"),
-                    (4, "Friday"),
-                    (5, "Saturday"),
-                    (6, "Sunday"),
-                ],
-                verbose_name="Week day",
-            ),
-        ),
-        migrations.AlterField(
-            model_name="validityrange",
-            name="site",
-            field=models.ForeignKey(
-                default=1,
-                editable=False,
-                on_delete=django.db.models.deletion.CASCADE,
-                related_name="+",
-                to="sites.site",
-            ),
-        ),
-    ]
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index ae323ccc7ce63f17e9c1224754cc4198f27304d6..052067f5465e127133888104e169cabff5b7148b 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -65,8 +65,8 @@ from aleksis.apps.cursus import models as cursus_models
 from aleksis.apps.cursus.models import Course
 from aleksis.apps.resint.models import LiveDocument
 from aleksis.core.managers import (
-    AlekSISBaseManagerWithoutMigrations,
     CurrentSiteManagerWithoutMigrations,
+    PolymorphicCurrentSiteManager,
 )
 from aleksis.core.mixins import (
     ExtensibleModel,
@@ -1374,7 +1374,7 @@ class LessonEvent(CalendarEvent):
     name = "lesson"
     verbose_name = _("Lessons")
 
-    objects = AlekSISBaseManagerWithoutMigrations.from_queryset(LessonEventQuerySet)()
+    objects = PolymorphicCurrentSiteManager.from_queryset(LessonEventQuerySet)()
 
     title = models.CharField(verbose_name=_("Name"), max_length=255, blank=True)
 
diff --git a/pyproject.toml b/pyproject.toml
index 26dbd51a260ebfc9741629fb2d1d9361b0c664d4..13b8386873c9e45c3a44b0a9855d153bb71277e0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-App-Chronos"
-version = "3.0.2.dev0"
+version = "4.0.dev0"
 packages = [
     { include = "aleksis" }
 ]
@@ -50,8 +50,8 @@ priority = "supplemental"
 [tool.poetry.dependencies]
 python = "^3.9"
 calendarweek = "^0.5.0"
-aleksis-core = "^3.0"
-aleksis-app-resint = "^3.0"
+aleksis-core = "^4.0.0.dev0"
+aleksis-app-resint = "^4.0.dev0"
 
 [tool.poetry.plugins."aleksis.app"]
 chronos = "aleksis.apps.chronos.apps:ChronosConfig"