diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 548390416a8d4968a6e43b5a0a136679c8ea4b38..9c2119a83c71645ced8e67124e8e601dfb31213e 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -4,7 +4,7 @@ from operator import itemgetter
 import os
 import pkgutil
 from importlib import import_module
-from typing import Any, Callable, Sequence, Union, List
+from typing import Any, Callable, Sequence, Union, List, Optional
 from uuid import uuid4
 
 from django.conf import settings
@@ -192,37 +192,13 @@ def now_tomorrow() -> datetime:
     return timezone.now() + timedelta(days=1)
 
 
-def get_person_by_pk(request: HttpRequest, id_: Optional[int] = None):
-    """ Get a person by its ID, defaulting to person in request's user """
-
-    from ..models import Person  # noqa
-
-    if id_:
-        return get_object_or_404(Person, pk=id_)
-    else:
-        return request.user.person
-
-
-def get_group_by_pk(request: HttpRequest, id_: Optional[int] = None) -> Group:
-    """ Get a group by its ID, defaulting to None """
-
-    if id_:
-        return get_object_or_404(Group, id=id_)
-
-    return None
-
-
-def get_announcement_by_pk(request: HttpRequest, id_: Optional[int] = None):
-    """ Get an announcement by its ID; defaulting to None """
-
-    if id_:
-        return get_object_or_404(Announcement, pk=pk)
-
-    return None
+def objectgetter_optional(model: Model, default: Optional[Any] = None, default_eval: bool = False) -> Callable[[HttpRequest, Optional[int]], Model]:
+    """ Get an object by pk, defaulting to None """
 
+    def get_object(request: HttpRequest, id_: Optional[int] = None) -> Model:
+        if id_ is not None:
+            return get_object_or_404(model, pk=id_)
+        else:
+            return eval(default) if default_eval else default
 
-def get_notification_by_pk(request: HttpRequest, pk: int):
-    try:
-        return get_object_or_404(Notification, pk=pk)
-    except:
-        return None
+    return get_object
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index bd1a0d8f045ab2f4e946060f92999905846d65d4..2cdd5284e8bddf2b284f3f9aa516d8c1ee1c6004 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -33,7 +33,7 @@ from .registries import site_preferences_registry, group_preferences_registry, p
 from .tables import GroupsTable, PersonsTable
 from .util import messages
 from .util.apps import AppConfig
-from .util.core_helpers import get_announcement_by_pk, get_group_by_pk, get_person_by_pk, get_notification_by_pk
+from .util.core_helpers import objectgetter_optional
 
 
 @permission_required("core.view_dashboard")
@@ -97,13 +97,13 @@ def persons(request: HttpRequest) -> HttpResponse:
     return render(request, "core/persons.html", context)
 
 
-@permission_required("core.view_person", fn=get_person_by_pk)
+@permission_required("core.view_person", fn=objectgetter_optional(Person, "request.user.person", True))
 def person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     """ Detail view for one person; defaulting to logged-in person """
 
     context = {}
 
-    person = get_person_by_pk(request, id_)
+    person = objectgetter_optional(Person, "request.user.person", True)(request, id_)
     context["person"] = person
 
     # Get groups where person is member of
@@ -117,13 +117,13 @@ def person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     return render(request, "core/person_full.html", context)
 
 
-@permission_required("core.view_group", fn=get_group_by_pk)
+@permission_required("core.view_group", fn=objectgetter_optional(Group, None, False))
 def group(request: HttpRequest, id_: int) -> HttpResponse:
     """ Detail view for one group """
 
     context = {}
 
-    group = get_group_by_pk(request, id_)
+    group = objectgetter_optional(Group, None, False)(request, id_)
     context["group"] = group
 
     # Get group
@@ -224,13 +224,13 @@ def groups_child_groups(request: HttpRequest) -> HttpResponse:
     return render(request, "core/groups_child_groups.html", context)
 
 
-@permission_required("core.edit_person", fn=get_person_by_pk)
+@permission_required("core.edit_person", fn=objectgetter_optional(Person, "request.user.person", True))
 def edit_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     """ Edit view for a single person, defaulting to logged-in person """
 
     context = {}
 
-    person = get_person_by_pk(request, id_)
+    person = objectgetter_optional(Person, "request.user.person", True)(request, id_)
     context["person"] = person
 
     edit_person_form = EditPersonForm(request.POST or None, request.FILES or None, instance=person)
@@ -255,13 +255,13 @@ def get_group_by_id(request: HttpRequest, id_: Optional[int] = None):
         return None
 
 
-@permission_required("core.edit_group", fn=get_group_by_pk)
+@permission_required("core.edit_group", fn=objectgetter_optional(Group, None, False))
 def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     """ View to edit or create a group """
 
     context = {}
 
-    group = get_group_by_pk(request, id_)
+    group = objectgetter_optional(Group, None, False)(request, id_)
     context["group"] = group
 
     if id_:
@@ -301,13 +301,13 @@ def system_status(request: HttpRequest) -> HttpResponse:
     return render(request, "core/system_status.html", context)
 
 
-@permission_required("core.mark_notification_as_read", fn=get_notification_by_pk)
+@permission_required("core.mark_notification_as_read", fn=objectgetter_optional(Notification, None, False))
 def notification_mark_read(request: HttpRequest, id_: int) -> HttpResponse:
     """ Mark a notification read """
 
     context = {}
 
-    notification = get_notification_by_pk(request, id_)
+    notification = objectgetter_optional(Notification, None, False)(request, id_)
 
     notification.read = True
     notification.save()
@@ -329,13 +329,13 @@ def announcements(request: HttpRequest) -> HttpResponse:
     return render(request, "core/announcement/list.html", context)
 
 
-@permission_required("core.create_or_edit_announcement", fn=get_announcement_by_pk)
-def announcement_form(request: HttpRequest, pk: Optional[int] = None) -> HttpResponse:
+@permission_required("core.create_or_edit_announcement", fn=objectgetter_optional(Announcement, None, False))
+def announcement_form(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     """ View to create or edit an announcement """
 
     context = {}
 
-    announcement = get_announcement_by_pk(request, pk)
+    announcement = objectgetter_optional(Announcement, None, False)(request, id_)
 
     if announcement:
         # Edit form for existing announcement
@@ -361,12 +361,12 @@ def announcement_form(request: HttpRequest, pk: Optional[int] = None) -> HttpRes
     return render(request, "core/announcement/form.html", context)
 
 
-@permission_required("core.delete_announcement", fn=get_announcement_by_pk)
-def delete_announcement(request: HttpRequest, pk: int) -> HttpResponse:
+@permission_required("core.delete_announcement", fn=objectgetter_optional(Announcement, None, False))
+def delete_announcement(request: HttpRequest, id_: int) -> HttpResponse:
     """ View to delete an announcement """
 
     if request.method == "POST":
-        announcement = get_announcement_by_pk(request, pk)
+        announcement = objectgetter_optional(Announcement, None, False)(request, id_)
         announcement.delete()
         messages.success(request, _("The announcement has been deleted."))