diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9f27536f909672ac526095117dd0aecb15d984f9..8ab6d80eebe0647d1bf5d291af9e6cf540a36ea6 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -15,6 +15,8 @@ Fixed
 * Register absence form wasn't accessible without direct access to class register.
 * Printing the full group register failed when a person had no personal notes.
 * Data checks reported all Lesson Documentations as being during Holidays if there was no Holiday object.
+* Students were displayed multiple times in class register views.
+* Absences were counted multiple times in some class register views.
 * Group owners couldn't create new seating plans.
 
 `2.1`_ - 2022-06-25
diff --git a/aleksis/apps/alsijil/model_extensions.py b/aleksis/apps/alsijil/model_extensions.py
index 5b0e5ac4b1337dfdc44c97470c36cd954fc7b915..b53f87f997b9f4b62336ef594fcc2676cc00a983 100644
--- a/aleksis/apps/alsijil/model_extensions.py
+++ b/aleksis/apps/alsijil/model_extensions.py
@@ -434,6 +434,7 @@ def generate_person_list_with_class_register_statistics(
             "filtered_personal_notes",
             filter=Q(filtered_personal_notes__absent=True)
             & ~Q(filtered_personal_notes__excuse_type__count_as_absent=False),
+            distinct=True,
         ),
         excused=Count(
             "filtered_personal_notes",
@@ -442,6 +443,7 @@ def generate_person_list_with_class_register_statistics(
                 filtered_personal_notes__excused=True,
             )
             & ~Q(filtered_personal_notes__excuse_type__count_as_absent=False),
+            distinct=True,
         ),
         excused_without_excuse_type=Count(
             "filtered_personal_notes",
@@ -450,15 +452,16 @@ def generate_person_list_with_class_register_statistics(
                 filtered_personal_notes__excused=True,
                 filtered_personal_notes__excuse_type__isnull=True,
             ),
+            distinct=True,
         ),
         unexcused=Count(
             "filtered_personal_notes",
             filter=Q(filtered_personal_notes__absent=True, filtered_personal_notes__excused=False),
+            distinct=True,
         ),
         tardiness=Sum("filtered_personal_notes__late"),
         tardiness_count=Count(
-            "filtered_personal_notes",
-            filter=Q(filtered_personal_notes__late__gt=0),
+            "filtered_personal_notes", filter=Q(filtered_personal_notes__late__gt=0), distinct=True
         ),
     )
 
diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py
index dc88dea6108ddc208142bf5b510f72f1563dbd47..68833a4d5dd8814a58c3bf6cae6b1c2e2c7af701 100644
--- a/aleksis/apps/alsijil/views.py
+++ b/aleksis/apps/alsijil/views.py
@@ -240,8 +240,10 @@ def register_object(
         else:
             persons = Person.objects.all()
 
-        persons_qs = register_object.get_personal_notes(persons, wanted_week).filter(
-            person__member_of__in=request.user.person.owner_of.all()
+        persons_qs = (
+            register_object.get_personal_notes(persons, wanted_week)
+            .filter(person__member_of__in=request.user.person.owner_of.all())
+            .distinct()
         )
 
         # Annotate group roles
@@ -476,12 +478,16 @@ def week_view(
         if not request.user.has_perm("alsijil.view_week_personalnote_rule", instance):
             persons_qs = persons_qs.filter(pk=request.user.person.pk)
         elif group:
-            persons_qs = persons_qs.filter(member_of=group).filter(
-                member_of__in=request.user.person.owner_of.all()
+            persons_qs = (
+                persons_qs.filter(member_of=group)
+                .filter(member_of__in=request.user.person.owner_of.all())
+                .distinct()
             )
         else:
-            persons_qs = persons_qs.filter(member_of__in=groups).filter(
-                member_of__in=request.user.person.owner_of.all()
+            persons_qs = (
+                persons_qs.filter(member_of__in=groups)
+                .filter(member_of__in=request.user.person.owner_of.all())
+                .distinct()
             )
 
         # Prefetch object permissions for persons and groups the persons are members of
@@ -792,12 +798,16 @@ def my_students(request: HttpRequest) -> HttpResponse:
 
     new_groups = []
     for group in relevant_groups:
-        persons = group.generate_person_list_with_class_register_statistics(
-            group.members.prefetch_related(
-                "primary_group__owners",
-                Prefetch("member_of", queryset=relevant_groups, to_attr="member_of_prefetched"),
+        persons = (
+            group.generate_person_list_with_class_register_statistics(
+                group.members.prefetch_related(
+                    "primary_group__owners",
+                    Prefetch("member_of", queryset=relevant_groups, to_attr="member_of_prefetched"),
+                )
             )
-        ).filter(member_of__in=request.user.person.owner_of.all())
+            .filter(member_of__in=request.user.person.owner_of.all())
+            .distinct()
+        )
         persons_for_group = []
         for person in persons:
             person.set_object_permission_checker(checker)
@@ -830,10 +840,10 @@ class StudentsList(PermissionRequiredMixin, DetailView):
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context["group"] = self.object
-        context[
-            "persons"
-        ] = self.object.generate_person_list_with_class_register_statistics().filter(
-            member_of__in=self.request.user.person.owner_of.all()
+        context["persons"] = (
+            self.object.generate_person_list_with_class_register_statistics()
+            .filter(member_of__in=self.request.user.person.owner_of.all())
+            .distinct()
         )
         context["extra_marks"] = ExtraMark.objects.all()
         context["excuse_types"] = ExcuseType.objects.filter(count_as_absent=True)
diff --git a/pyproject.toml b/pyproject.toml
index 1381bc6d33e3ef546a6555d1e8695cae267f33d9..eb3cff73affb6750005381f2b2f03d818f1c089f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -48,7 +48,7 @@ secondary = true
 
 [tool.poetry.dependencies]
 python = "^3.9"
-aleksis-core = "^2.7"
+aleksis-core = "^2.11"
 aleksis-app-chronos = "^2.2"
 aleksis-app-stoelindeling = { version = "^1.0", optional = true }
 
diff --git a/tox.ini b/tox.ini
index 749e0606f4f02fcbd1649627219b15850cbc0a90..78e09567e193b72a299dfb3f776499420ecc04ec 100644
--- a/tox.ini
+++ b/tox.ini
@@ -10,7 +10,7 @@ skip_install = true
 envdir = {toxworkdir}/globalenv
 commands_pre =
      poetry install
-     poetry run aleksis-admin yarn install
+     poetry run aleksis-admin webpack_bundle
      poetry run aleksis-admin collectstatic --no-input
 commands =
     poetry run pytest --cov=. {posargs} aleksis/