diff --git a/aleksis/core/__init__.py b/aleksis/core/__init__.py
index 8025958440c84991c6d28b463bde735bae2efcbc..21a49f0785f3977d9a265059a32ec957c9e1eb3c 100644
--- a/aleksis/core/__init__.py
+++ b/aleksis/core/__init__.py
@@ -1,5 +1,3 @@
-from django.utils.translation import gettext_lazy as _
-
 import pkg_resources
 
 try:
diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py
index 921d12ff785c39c76ac0af63cdb73d9732faaf80..93b383001d6e7a96e9416467d13fcfcfa182277f 100644
--- a/aleksis/core/apps.py
+++ b/aleksis/core/apps.py
@@ -1,9 +1,8 @@
 from typing import Any, List, Optional, Tuple
 
 import django.apps
-from django.contrib.auth.signals import user_logged_in
 from django.http import HttpRequest
-from django.utils.translation import gettext_lazy as _
+from django.shortcuts import get_user_model
 
 from dynamic_preferences.registries import preference_models
 
@@ -17,6 +16,9 @@ from .util.core_helpers import has_person
 from .util.sass_helpers import clean_scss
 
 
+User = get_user_model()
+
+
 class CoreConfig(AppConfig):
     name = "aleksis.core"
     verbose_name = "AlekSIS — The Free School Information System"
diff --git a/aleksis/core/checks.py b/aleksis/core/checks.py
index 19c8b77bab78db18441e71f8efe49bd797b1e9e2..c1a3dfb242946c67bf484fb8c9b485ec9c0b1b06 100644
--- a/aleksis/core/checks.py
+++ b/aleksis/core/checks.py
@@ -22,8 +22,12 @@ def check_app_configs_base_class(
         if not isinstance(app_config, AppConfig):
             results.append(
                 Warning(
-                    f"App config {app_config.name} does not derive from aleksis.core.util.apps.AppConfig.",
-                    hint="Ensure the app uses the correct base class for all registry functionality to work.",
+                    f"App config {app_config.name} does not derive"
+                    "from aleksis.core.util.apps.AppConfig.",
+                    hint=(
+                        "Ensure the app uses the correct base class for all"
+                        "registry functionality to work."
+                    ),
                     obj=app_config,
                     id="aleksis.core.W001",
                 )
@@ -48,8 +52,13 @@ def check_app_models_base_class(
             if ExtensibleModel not in model.__mro__ and PureDjangoModel not in model.__mro__:
                 results.append(
                     Warning(
-                        f"Model {model._meta.object_name} in app config {app_config.name} does not derive from aleksis.core.mixins.ExtensibleModel.",
-                        hint="Ensure all models in AlekSIS use ExtensibleModel as base. If your deviation is intentional, you can add the PureDjangoModel mixin instead to silence this warning.",
+                        f"Model {model._meta.object_name} in app config {app_config.name} does"
+                        "not derive from aleksis.core.mixins.ExtensibleModel.",
+                        hint=(
+                            "Ensure all models in AlekSIS use ExtensibleModel as base."
+                            "If your deviation is intentional, you can add the PureDjangoModel"
+                            "mixin instead to silence this warning."
+                        ),
                         obj=model,
                         id="aleksis.core.W002",
                     )
diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py
index a7989eb4842e4e90291a7b92ab8bdee4805e71ba..09f57a249ef556855e8070f68c37199a80b66386 100644
--- a/aleksis/core/forms.py
+++ b/aleksis/core/forms.py
@@ -1,11 +1,8 @@
 from datetime import datetime, time
-from typing import Optional
 
 from django import forms
 from django.contrib.auth import get_user_model
-from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
-from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
 from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget
@@ -13,7 +10,7 @@ from dynamic_preferences.forms import PreferenceForm
 from material import Fieldset, Layout, Row
 
 from .mixins import ExtensibleForm
-from .models import Announcement, AnnouncementRecipient, Group, Person
+from .models import Announcement, Group, Person
 from .registries import (
     group_preferences_registry,
     person_preferences_registry,
diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index 35fb855c6062c72192a33049ae8bb6ae861e6176..b7401b6137e0e41f30f27f42275b93420603e7fd 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -17,7 +17,7 @@ from rules.contrib.admin import ObjectPermissionsModelAdmin
 
 
 @reversion.register()
-class ExtensibleModel(CRUDMixin):
+class ExtensibleModel():
     """ Base model for all objects in AlekSIS apps
 
     This base model ensures all objects in AlekSIS apps fulfill the
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 542a4025512ad37f6a45ea048819f9599abc413d..bf92167d1dcbbd3d0a805c0542469c6aed16afd4 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -474,7 +474,9 @@ class Announcement(ExtensibleModel):
         return persons
 
     def get_recipients_for_model(self, obj: Union[models.Model]) -> Sequence[models.Model]:
-        """ Get all recipients for this announcement with a special content type (provided through model) """
+        """ Get all recipients for this announcement
+        with a special content type (provided through model)
+        """
 
         ct = ContentType.objects.get_for_model(obj)
         return [r.recipient for r in self.recipients.filter(content_type=ct)]
@@ -533,8 +535,9 @@ class DashboardWidget(PolymorphicModel, PureDjangoModel):
 
     If your widget does not add any database fields, you should mark it as a proxy model.
 
-    You can provide a Media meta class with custom JS and CSS files which will be added to html head.
-    For further information on media definition see https://docs.djangoproject.com/en/3.0/topics/forms/media/
+    You can provide a Media meta class with custom JS and CSS files which
+    will be added to html head.  For further information on media definition
+    see https://docs.djangoproject.com/en/3.0/topics/forms/media/
 
     Example::
 
diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py
index c363875824b5ebba86637c5c557953233278982f..56e7b48d53cd7342743dcd644fa688d277054ba0 100644
--- a/aleksis/core/preferences.py
+++ b/aleksis/core/preferences.py
@@ -2,18 +2,14 @@ from django.conf import settings
 from django.forms import EmailField, ImageField, URLField
 from django.utils.translation import gettext_lazy as _
 
-from colorfield.widgets import ColorWidget
 from dynamic_preferences.preferences import Section
-from dynamic_preferences.registries import global_preferences_registry
 from dynamic_preferences.types import (
-    BooleanPreference,
     ChoicePreference,
     FilePreference,
     StringPreference,
 )
 
 from .registries import (
-    group_preferences_registry,
     person_preferences_registry,
     site_preferences_registry,
 )
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 3153f9d8dd83b128ba8c35852c6addcb4c3fe599..b73208afb2ba440d15432ebe0e7453cf3df80613 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -1,9 +1,6 @@
 import os
-import sys
 from glob import glob
-from importlib import import_module
 
-from django.apps import apps
 from django.utils.translation import gettext_lazy as _
 
 from dynaconf import LazySettings
@@ -482,7 +479,10 @@ PWA_APP_SPLASH_SCREEN = [
         "src": lazy_get_favicon_url(
             title="pwa_icon", size=192, rel="apple", default=STATIC_URL + "icons/apple_180.png"
         ),
-        "media": "(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)",
+        "media": (
+            "(device-width: 320px) and (device-height: 568px) and"
+            "(-webkit-device-pixel-ratio: 2)"
+        ),
     }
 ]
 
diff --git a/aleksis/core/tasks.py b/aleksis/core/tasks.py
index 9a9f1ea39ac3b95aade5d6fffa21e766ab042f0f..48f73ac0a8ffa00b4e4afd751c73526c8fb5149b 100644
--- a/aleksis/core/tasks.py
+++ b/aleksis/core/tasks.py
@@ -1,3 +1,4 @@
+from django.conf import settings
 from django.core import management
 
 from .util.core_helpers import celery_optional
diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py
index 6f58fc46e909db034f6a61d210a5e6bddba3868f..f5b7aa9e9d15f39561a73b5a87fcaeb54fc8fbe6 100644
--- a/aleksis/core/urls.py
+++ b/aleksis/core/urls.py
@@ -9,7 +9,6 @@ from django.views.i18n import JavaScriptCatalog
 import calendarweek.django
 import debug_toolbar
 from django_js_reverse.views import urls_js
-from rules.contrib.views import permission_required
 from two_factor.urls import urlpatterns as tf_urls
 
 from . import views
diff --git a/aleksis/core/util/apps.py b/aleksis/core/util/apps.py
index c1162d4ea8e49d3fbbcde7777ce7f851569c512b..8d41b2d89f03d3f5eb32a6ad5335507c33951244 100644
--- a/aleksis/core/util/apps.py
+++ b/aleksis/core/util/apps.py
@@ -2,17 +2,21 @@ from importlib import import_module
 from typing import Any, List, Optional, Sequence, Tuple
 
 import django.apps
+from django.contrib.auth import get_user_model
 from django.contrib.auth.signals import user_logged_in, user_logged_out
 from django.db.models.signals import post_migrate, pre_migrate
 from django.http import HttpRequest
 
 from dynamic_preferences.signals import preference_updated
-from license_expression import LicenseSymbol, Licensing
+from license_expression import Licensing
 from spdx_license_list import LICENSES
 
 from .core_helpers import copyright_years
 
 
+User = get_user_model()
+
+
 class AppConfig(django.apps.AppConfig):
     """ An extended version of DJango's AppConfig container. """
 
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index aa47102931de63a881e2e76e26cc7d484bdff933..2f44503e73251fb9b82398c627169111b97ba40e 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -4,7 +4,7 @@ from datetime import datetime, timedelta
 from importlib import import_module
 from itertools import groupby
 from operator import itemgetter
-from typing import Any, Callable, List, Optional, Sequence, Union
+from typing import Any, Callable, Optional, Sequence, Union
 from uuid import uuid4
 
 from django.conf import settings
@@ -12,6 +12,7 @@ from django.db.models import Model
 from django.http import HttpRequest
 from django.utils import timezone
 from django.utils.functional import lazy
+from django.shortcuts import get_object_or_404
 
 
 def copyright_years(years: Sequence[int], seperator: str = ", ", joiner: str = "–") -> str:
diff --git a/aleksis/core/util/middlewares.py b/aleksis/core/util/middlewares.py
index 79f15a1393dc93d1571e70d843d81ec6e31993d4..fc86082ececa88da0384ec8fcd987aa08b638648 100644
--- a/aleksis/core/util/middlewares.py
+++ b/aleksis/core/util/middlewares.py
@@ -1,8 +1,6 @@
 from typing import Callable
 
-from django.core.exceptions import PermissionDenied
 from django.http import HttpRequest, HttpResponse
-from django.utils.translation import gettext_lazy as _
 
 from ..models import DummyPerson
 from .core_helpers import has_person
diff --git a/aleksis/core/util/notifications.py b/aleksis/core/util/notifications.py
index 7ab63a64e93ab595b16d6c92b50940b8946d0c00..fd294e5a1b5368929c40cc16c1187f6d671a3bb3 100644
--- a/aleksis/core/util/notifications.py
+++ b/aleksis/core/util/notifications.py
@@ -10,7 +10,8 @@ from django.utils.translation import gettext_lazy as _
 
 from templated_email import send_templated_mail
 
-from .core_helpers import celery_optional, lazy_preference
+from .models import Notification
+from .core_helpers import lazy_preference
 
 try:
     from twilio.rest import Client as TwilioClient
diff --git a/aleksis/core/util/predicates.py b/aleksis/core/util/predicates.py
index 6c8deb1322b1b5407e04fe0de3a2f37322b182b9..d76df8310eac7cfbeae2bb60b846f4092dbc9d4f 100644
--- a/aleksis/core/util/predicates.py
+++ b/aleksis/core/util/predicates.py
@@ -58,7 +58,9 @@ def has_object_perm(perm: str):
 
 
 def has_any_object(perm: str, klass):
-    """ Build predicate which checks whether a user has access to objects with the provided permission """
+    """ Build predicate which checks whether a user has access
+    to objects with the provided permission
+    """
 
     name = f"has_any_object:{perm}"
 
@@ -93,6 +95,8 @@ def is_group_owner(user: User, group: Group) -> bool:
 
 @predicate
 def is_notification_recipient(user: User, obj: Model) -> bool:
-    """ Predicate which checks whether the recipient of the notification a user wants to mark read is this user """
+    """ Predicate which checks whether the recipient of the
+    notification a user wants to mark read is this user
+    """
 
     return user == obj.recipient.user
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index fab71fd0c306f0a471c4f6a31e54517648c7b016..49594d64721d0cd27216df529fb4f8e46b95b028 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -1,4 +1,3 @@
-from importlib import import_module
 from typing import Optional
 
 from django.apps import apps
@@ -28,7 +27,7 @@ from .forms import (
     PersonsAccountsFormSet,
     SitePreferenceForm,
 )
-from .models import Activity, Announcement, DashboardWidget, Group, Notification, Person
+from .models import Announcement, DashboardWidget, Group, Notification, Person
 from .registries import (
     group_preferences_registry,
     person_preferences_registry,
@@ -317,8 +316,6 @@ def system_status(request: HttpRequest) -> HttpResponse:
 def notification_mark_read(request: HttpRequest, id_: int) -> HttpResponse:
     """ Mark a notification read """
 
-    context = {}
-
     notification = objectgetter_optional(Notification, None, False)(request, id_)
 
     notification.read = True
@@ -431,14 +428,14 @@ def preferences(
             raise PermissionDenied()
     elif registry_name == "person":
         registry = person_preferences_registry
-        instance = get_person_by_pk(request, pk)
+        instance = objectgetter_optional(Person, None, False)(request, pk)
         form_class = PersonPreferenceForm
 
         if not request.user.has_perm("core.change_person_preferences", instance):
             raise PermissionDenied()
     elif registry_name == "group":
         registry = group_preferences_registry
-        instance = get_group_by_pk(request, pk)
+        instance = objectgetter_optional(Group, None, False)(request, pk)
         form_class = GroupPreferenceForm
 
         if not request.user.has_perm("core.change_group_preferences", instance):