diff --git a/.docker/extra_requirements.txt b/.docker/extra_requirements.txt
index 55e14c229a0c7e179c89afe7ab63e9b574fbc70b..f8498f044fad1c233232723f0c40bca1a82bc536 100644
--- a/.docker/extra_requirements.txt
+++ b/.docker/extra_requirements.txt
@@ -1 +1 @@
-uwsgi==2.0.25.1
+uwsgi==2.0.28
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5855c87c8f33c1695f0fb005197a1fba63f1179b..4cde1bfb74cba5daf1c6a4b734edce8ad68a5cd6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: python:3.10
+image: python:3.11
 
 services:
   - mysql
@@ -26,10 +26,9 @@ cache:
     - pip install pylint-gitlab pylint-django
     - mysql --version
 
-check:
+migrations:
   extends: .before_script_template
   script:
-    - ./Utils/check.sh --all
     - source venv/bin/activate
     - ./manage.py makemigrations --dry-run --check
 
diff --git a/AKDashboard/tests.py b/AKDashboard/tests.py
index 65b59fd9cdea19830b87b2577f53886619277a27..59328adf517d22a1793df63f67782254b0958f94 100644
--- a/AKDashboard/tests.py
+++ b/AKDashboard/tests.py
@@ -1,11 +1,12 @@
 import zoneinfo
+
 from django.apps import apps
-from django.test import TestCase, override_settings
+from django.test import override_settings, TestCase
 from django.urls import reverse
 from django.utils.timezone import now
 
 from AKDashboard.models import DashboardButton
-from AKModel.models import Event, AK, AKCategory
+from AKModel.models import AK, AKCategory, Event
 from AKModel.tests.test_views import BasicViewTests
 
 
@@ -13,6 +14,7 @@ class DashboardTests(TestCase):
     """
     Specific Dashboard Tests
     """
+
     @classmethod
     def setUpTestData(cls):
         """
@@ -20,17 +22,17 @@ class DashboardTests(TestCase):
         """
         super().setUpTestData()
         cls.event = Event.objects.create(
-            name="Dashboard Test Event",
-            slug="dashboardtest",
-            timezone=zoneinfo.ZoneInfo("Europe/Berlin"),
-            start=now(),
-            end=now(),
-            active=True,
-            plan_hidden=False,
+                name="Dashboard Test Event",
+                slug="dashboardtest",
+                timezone=zoneinfo.ZoneInfo("Europe/Berlin"),
+                start=now(),
+                end=now(),
+                active=True,
+                plan_hidden=False,
         )
         cls.default_category = AKCategory.objects.create(
-            name="Test Category",
-            event=cls.event,
+                name="Test Category",
+                event=cls.event,
         )
 
     def test_dashboard_view(self):
@@ -62,12 +64,12 @@ class DashboardTests(TestCase):
 
         # History should be empty
         response = self.client.get(url)
-        self.assertQuerysetEqual(response.context["recent_changes"], [])
+        self.assertQuerySetEqual(response.context["recent_changes"], [])
 
         AK.objects.create(
-            name="Test AK",
-            category=self.default_category,
-            event=self.event,
+                name="Test AK",
+                category=self.default_category,
+                event=self.event,
         )
 
         # History should now contain one AK (Test AK)
@@ -154,8 +156,8 @@ class DashboardTests(TestCase):
         self.assertNotContains(response, "Dashboard Button Test")
 
         DashboardButton.objects.create(
-            text="Dashboard Button Test",
-            event=self.event
+                text="Dashboard Button Test",
+                event=self.event
         )
 
         response = self.client.get(url_event_dashboard)
diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po
index 38b3d54a9101367a201b23ac589ff61f217d7775..00409411289c42f855f3f8a048a4175d87424800 100644
--- a/AKModel/locale/de_DE/LC_MESSAGES/django.po
+++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-03-03 00:42+0000\n"
+"POT-Creation-Date: 2025-03-04 17:35+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -33,8 +33,8 @@ msgstr "Plan veröffentlichen"
 msgid "Unpublish plan"
 msgstr "Plan verbergen"
 
-#: AKModel/admin.py:170 AKModel/models.py:875 AKModel/models.py:1329
-#: AKModel/models.py:1365 AKModel/templates/admin/AKModel/aks_by_user.html:12
+#: AKModel/admin.py:170 AKModel/models.py:892 AKModel/models.py:1349
+#: AKModel/models.py:1385 AKModel/templates/admin/AKModel/aks_by_user.html:12
 #: AKModel/templates/admin/AKModel/status/event_aks.html:10
 #: AKModel/views/manage.py:75 AKModel/views/status.py:102
 msgid "AKs"
@@ -60,11 +60,11 @@ msgstr "In Wiki-Syntax exportieren"
 msgid "Cannot export AKs from more than one event at the same time."
 msgstr "Kann nicht AKs von mehreren Events zur selben Zeit exportieren."
 
-#: AKModel/admin.py:335 AKModel/views/ak.py:123
+#: AKModel/admin.py:335 AKModel/views/ak.py:120
 msgid "Reset interest in AKs"
 msgstr "Interesse an AKs zurücksetzen"
 
-#: AKModel/admin.py:345 AKModel/views/ak.py:138
+#: AKModel/admin.py:345 AKModel/views/ak.py:135
 msgid "Reset AKs' interest counters"
 msgstr "Interessenszähler der AKs zurücksetzen"
 
@@ -125,19 +125,19 @@ msgstr "Die eingegebene Verfügbarkeit enthält ein ungültiges Datum."
 msgid "Please fill in your availabilities!"
 msgstr "Bitte Verfügbarkeiten eintragen!"
 
-#: AKModel/availability/models.py:43 AKModel/models.py:166
-#: AKModel/models.py:654 AKModel/models.py:731 AKModel/models.py:764
-#: AKModel/models.py:790 AKModel/models.py:809 AKModel/models.py:865
-#: AKModel/models.py:1023 AKModel/models.py:1100 AKModel/models.py:1268
-#: AKModel/models.py:1325 AKModel/models.py:1516
+#: AKModel/availability/models.py:43 AKModel/models.py:179
+#: AKModel/models.py:669 AKModel/models.py:746 AKModel/models.py:779
+#: AKModel/models.py:805 AKModel/models.py:824 AKModel/models.py:882
+#: AKModel/models.py:1041 AKModel/models.py:1118 AKModel/models.py:1287
+#: AKModel/models.py:1345 AKModel/models.py:1537
 msgid "Event"
 msgstr "Event"
 
-#: AKModel/availability/models.py:44 AKModel/models.py:655
-#: AKModel/models.py:732 AKModel/models.py:765 AKModel/models.py:791
-#: AKModel/models.py:810 AKModel/models.py:866 AKModel/models.py:1024
-#: AKModel/models.py:1101 AKModel/models.py:1269 AKModel/models.py:1326
-#: AKModel/models.py:1517
+#: AKModel/availability/models.py:44 AKModel/models.py:670
+#: AKModel/models.py:747 AKModel/models.py:780 AKModel/models.py:806
+#: AKModel/models.py:825 AKModel/models.py:883 AKModel/models.py:1042
+#: AKModel/models.py:1119 AKModel/models.py:1288 AKModel/models.py:1346
+#: AKModel/models.py:1538
 msgid "Associated event"
 msgstr "Zugehöriges Event"
 
@@ -149,8 +149,8 @@ msgstr "Person"
 msgid "Person whose availability this is"
 msgstr "Person deren Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:61 AKModel/models.py:1027
-#: AKModel/models.py:1090 AKModel/models.py:1335
+#: AKModel/availability/models.py:61 AKModel/models.py:1045
+#: AKModel/models.py:1108 AKModel/models.py:1355
 msgid "Room"
 msgstr "Raum"
 
@@ -158,8 +158,8 @@ msgstr "Raum"
 msgid "Room whose availability this is"
 msgstr "Raum dessen Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:70 AKModel/models.py:874
-#: AKModel/models.py:1089 AKModel/models.py:1263
+#: AKModel/availability/models.py:70 AKModel/models.py:891
+#: AKModel/models.py:1107 AKModel/models.py:1282
 msgid "AK"
 msgstr "AK"
 
@@ -167,8 +167,8 @@ msgstr "AK"
 msgid "AK whose availability this is"
 msgstr "Verfügbarkeiten"
 
-#: AKModel/availability/models.py:79 AKModel/models.py:735
-#: AKModel/models.py:1341
+#: AKModel/availability/models.py:79 AKModel/models.py:750
+#: AKModel/models.py:1361
 msgid "AK Category"
 msgstr "AK-Kategorie"
 
@@ -176,7 +176,7 @@ msgstr "AK-Kategorie"
 msgid "AK Category whose availability this is"
 msgstr "AK-Kategorie, deren Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:309 AKModel/models.py:923
+#: AKModel/availability/models.py:309 AKModel/models.py:940
 msgid "Availabilities"
 msgstr "Verfügbarkeiten"
 
@@ -242,7 +242,7 @@ msgstr ""
 "fürWünsche markieren, z.B. um während der Präsentation auf einem Touchscreen "
 "ausgefüllt zu werden?"
 
-#: AKModel/forms.py:198 AKModel/models.py:1510
+#: AKModel/forms.py:198 AKModel/models.py:1531
 msgid "Default Slots"
 msgstr "Standardslots"
 
@@ -289,7 +289,7 @@ msgstr "JSON-Daten"
 msgid "JSON data from the scheduling solver"
 msgstr "JSON-Daten, die der scheduling-solver produziert hat"
 
-#: AKModel/metaviews/admin.py:156 AKModel/models.py:129
+#: AKModel/metaviews/admin.py:156 AKModel/models.py:141
 msgid "Start"
 msgstr "Start"
 
@@ -314,67 +314,75 @@ msgstr "Aktivieren?"
 msgid "Finish"
 msgstr "Abschluss"
 
-#: AKModel/models.py:120 AKModel/models.py:723 AKModel/models.py:761
-#: AKModel/models.py:788 AKModel/models.py:807 AKModel/models.py:825
-#: AKModel/models.py:1015
+#: AKModel/models.py:26
+msgid "May not contain quotation marks"
+msgstr "Darf keine Anführungszeichen enthalten"
+
+#: AKModel/models.py:29
+msgid "Must contain at least one letter or digit"
+msgstr "Muss mindestens einen Buchstaben oder eine Ziffer enthalten"
+
+#: AKModel/models.py:132 AKModel/models.py:738 AKModel/models.py:776
+#: AKModel/models.py:803 AKModel/models.py:822 AKModel/models.py:840
+#: AKModel/models.py:1033
 msgid "Name"
 msgstr "Name"
 
-#: AKModel/models.py:121
+#: AKModel/models.py:133
 msgid "Name or iteration of the event"
 msgstr "Name oder Iteration des Events"
 
-#: AKModel/models.py:122
+#: AKModel/models.py:134
 msgid "Short Form"
 msgstr "Kurzer Name"
 
-#: AKModel/models.py:123
+#: AKModel/models.py:135
 msgid "Short name of letters/numbers/dots/dashes/underscores used in URLs."
 msgstr ""
 "Kurzname bestehend aus Buchstaben, Nummern, Punkten und Unterstrichen zur "
 "Nutzung in URLs"
 
-#: AKModel/models.py:125
+#: AKModel/models.py:137
 msgid "Place"
 msgstr "Ort"
 
-#: AKModel/models.py:126
+#: AKModel/models.py:138
 msgid "City etc. the event takes place in"
 msgstr "Stadt o.ä. in der das Event stattfindet"
 
-#: AKModel/models.py:128
+#: AKModel/models.py:140
 msgid "Time Zone"
 msgstr "Zeitzone"
 
-#: AKModel/models.py:128
+#: AKModel/models.py:140
 msgid "Time Zone where this event takes place in"
 msgstr "Zeitzone in der das Event stattfindet"
 
-#: AKModel/models.py:129
+#: AKModel/models.py:141
 msgid "Time the event begins"
 msgstr "Zeit zu der das Event beginnt"
 
-#: AKModel/models.py:130
+#: AKModel/models.py:142
 msgid "End"
 msgstr "Ende"
 
-#: AKModel/models.py:130
+#: AKModel/models.py:142
 msgid "Time the event ends"
 msgstr "Zeit zu der das Event endet"
 
-#: AKModel/models.py:131
+#: AKModel/models.py:143
 msgid "Resolution Deadline"
 msgstr "Resolutionsdeadline"
 
-#: AKModel/models.py:132
+#: AKModel/models.py:144
 msgid "When should AKs with intention to submit a resolution be done?"
 msgstr "Wann sollen AKs mit Resolutionsabsicht stattgefunden haben?"
 
-#: AKModel/models.py:134
+#: AKModel/models.py:146
 msgid "Interest Window Start"
 msgstr "Beginn Interessensbekundung"
 
-#: AKModel/models.py:136
+#: AKModel/models.py:148
 msgid ""
 "Opening time for expression of interest. When left blank, no interest "
 "indication will be possible."
@@ -382,71 +390,71 @@ msgstr ""
 "Öffnungszeitpunkt für die Angabe von Interesse an AKs.Wenn das Feld leer "
 "bleibt, wird keine Abgabe von Interesse möglich sein."
 
-#: AKModel/models.py:138
+#: AKModel/models.py:151
 msgid "Interest Window End"
 msgstr "Ende Interessensbekundung"
 
-#: AKModel/models.py:139
+#: AKModel/models.py:152
 msgid "Closing time for expression of interest."
 msgstr "Öffnungszeitpunkt für die Angabe von Interesse an AKs."
 
-#: AKModel/models.py:141
+#: AKModel/models.py:154
 msgid "Public event"
 msgstr "Öffentliches Event"
 
-#: AKModel/models.py:142
+#: AKModel/models.py:155
 msgid "Show this event on overview page."
 msgstr "Zeige dieses Event auf der Übersichtseite an"
 
-#: AKModel/models.py:144
+#: AKModel/models.py:157
 msgid "Active State"
 msgstr "Aktiver Status"
 
-#: AKModel/models.py:144
+#: AKModel/models.py:157
 msgid "Marks currently active events"
 msgstr "Markiert aktuell aktive Events"
 
-#: AKModel/models.py:145
+#: AKModel/models.py:158
 msgid "Plan Hidden"
 msgstr "Plan verborgen"
 
-#: AKModel/models.py:145
+#: AKModel/models.py:158
 msgid "Hides plan for non-staff users"
 msgstr "Verbirgt den Plan für Nutzer*innen ohne erweiterte Rechte"
 
-#: AKModel/models.py:147
+#: AKModel/models.py:160
 msgid "Plan published at"
 msgstr "Plan veröffentlicht am/um"
 
-#: AKModel/models.py:148
+#: AKModel/models.py:161
 msgid "Timestamp at which the plan was published"
 msgstr "Zeitpunkt, zu dem der Plan veröffentlicht wurde"
 
-#: AKModel/models.py:150
+#: AKModel/models.py:163
 msgid "Base URL"
 msgstr "URL-Prefix"
 
-#: AKModel/models.py:150
+#: AKModel/models.py:163
 msgid "Prefix for wiki link construction"
 msgstr "Prefix für die automatische Generierung von Wiki-Links"
 
-#: AKModel/models.py:151
+#: AKModel/models.py:164
 msgid "Wiki Export Template Name"
 msgstr "Wiki-Export Templatename"
 
-#: AKModel/models.py:152
+#: AKModel/models.py:165
 msgid "Default Slot Length"
 msgstr "Standardslotlänge"
 
-#: AKModel/models.py:153
+#: AKModel/models.py:166
 msgid "Default length in hours that is assumed for AKs in this event."
 msgstr "Standardlänge von Slots (in Stunden) für dieses Event"
 
-#: AKModel/models.py:154
+#: AKModel/models.py:167
 msgid "Export Slot Length"
 msgstr "Export-Slotlänge"
 
-#: AKModel/models.py:156
+#: AKModel/models.py:169
 msgid ""
 "Slot duration in hours that is used in the timeslot discretization, when "
 "this event is exported for the solver."
@@ -454,11 +462,11 @@ msgstr ""
 "Länge von Slots (in Stunden) in der Zeitslot-Diskretisierung beim JSON-"
 "Export dieses Events."
 
-#: AKModel/models.py:161
+#: AKModel/models.py:174
 msgid "Contact email address"
 msgstr "E-Mail Kontaktadresse"
 
-#: AKModel/models.py:162
+#: AKModel/models.py:175
 msgid ""
 "An email address that is displayed on every page and can be used for all "
 "kinds of questions"
@@ -466,16 +474,16 @@ msgstr ""
 "Eine Mailadresse die auf jeder Seite angezeigt wird und für alle Arten von "
 "Fragen genutzt werden kann"
 
-#: AKModel/models.py:167
+#: AKModel/models.py:180
 msgid "Events"
 msgstr "Events"
 
-#: AKModel/models.py:444
+#: AKModel/models.py:457
 #, python-brace-format
 msgid "AK {ak_name} is not assigned any timeslot by the solver"
 msgstr "Dem AK {ak_name} wurde vom Solver kein Zeitslot zugewiesen"
 
-#: AKModel/models.py:454
+#: AKModel/models.py:467
 #, python-brace-format
 msgid ""
 "Duration of AK {ak_name} assigned by solver ({solver_duration} hours) is "
@@ -485,7 +493,7 @@ msgstr ""
 "Stunden) ist kürzer als die aktuell vorgesehene Dauer des Slots "
 "({slot_duration} Stunden)"
 
-#: AKModel/models.py:468
+#: AKModel/models.py:481
 #, python-brace-format
 msgid ""
 "Fixed AK {ak_name} assigned by solver to room {solver_room} is fixed to room "
@@ -494,7 +502,7 @@ msgstr ""
 "Dem fix geplanten AK {ak_name} wurde vom Solver Raum {solver_room} "
 "zugewiesen, dabei ist der AK bereits fix in Raum {slot_room} eingeplant."
 
-#: AKModel/models.py:479
+#: AKModel/models.py:492
 #, python-brace-format
 msgid ""
 "Fixed AK {ak_name} assigned by solver to start at {solver_start} is fixed to "
@@ -503,71 +511,71 @@ msgstr ""
 "Dem fix geplanten AK {ak_name} wurde vom Solver die Startzeit {solver_start} "
 "zugewiesen, dabei ist der AK bereits für {slot_start} eingeplant."
 
-#: AKModel/models.py:649
+#: AKModel/models.py:662
 msgid "Nickname"
 msgstr "Spitzname"
 
-#: AKModel/models.py:649
+#: AKModel/models.py:664
 msgid "Name to identify an AK owner by"
 msgstr "Name, durch den eine AK-Leitung identifiziert wird"
 
-#: AKModel/models.py:650
+#: AKModel/models.py:665
 msgid "Slug"
 msgstr "Slug"
 
-#: AKModel/models.py:650
+#: AKModel/models.py:665
 msgid "Slug for URL generation"
 msgstr "Slug für URL-Generierung"
 
-#: AKModel/models.py:651
+#: AKModel/models.py:666
 msgid "Institution"
 msgstr "Instutution"
 
-#: AKModel/models.py:651
+#: AKModel/models.py:666
 msgid "Uni etc."
 msgstr "Universität o.ä."
 
-#: AKModel/models.py:652 AKModel/models.py:834
+#: AKModel/models.py:667 AKModel/models.py:851
 msgid "Web Link"
 msgstr "Internet Link"
 
-#: AKModel/models.py:652
+#: AKModel/models.py:667
 msgid "Link to Homepage"
 msgstr "Link zu Homepage oder Webseite"
 
-#: AKModel/models.py:658 AKModel/models.py:1334
+#: AKModel/models.py:673 AKModel/models.py:1354
 msgid "AK Owner"
 msgstr "AK-Leitung"
 
-#: AKModel/models.py:659
+#: AKModel/models.py:674
 msgid "AK Owners"
 msgstr "AK-Leitungen"
 
-#: AKModel/models.py:723
+#: AKModel/models.py:738
 msgid "Name of the AK Category"
 msgstr "Name der AK-Kategorie"
 
-#: AKModel/models.py:724 AKModel/models.py:762
+#: AKModel/models.py:739 AKModel/models.py:777
 msgid "Color"
 msgstr "Farbe"
 
-#: AKModel/models.py:724 AKModel/models.py:762
+#: AKModel/models.py:739 AKModel/models.py:777
 msgid "Color for displaying"
 msgstr "Farbe für die Anzeige"
 
-#: AKModel/models.py:725 AKModel/models.py:828
+#: AKModel/models.py:740 AKModel/models.py:845
 msgid "Description"
 msgstr "Beschreibung"
 
-#: AKModel/models.py:726
+#: AKModel/models.py:741
 msgid "Short description of this AK Category"
 msgstr "Beschreibung der AK-Kategorie"
 
-#: AKModel/models.py:727
+#: AKModel/models.py:742
 msgid "Present by default"
 msgstr "Defaultmäßig präsentieren"
 
-#: AKModel/models.py:728
+#: AKModel/models.py:743
 msgid ""
 "Present AKs of this category by default if AK owner did not specify whether "
 "this AK should be presented?"
@@ -575,152 +583,152 @@ msgstr ""
 "AKs dieser Kategorie standardmäßig vorstellen, wenn die Leitungen das für "
 "ihren AK nicht explizit spezifiziert haben?"
 
-#: AKModel/models.py:736
+#: AKModel/models.py:751
 msgid "AK Categories"
 msgstr "AK-Kategorien"
 
-#: AKModel/models.py:761
+#: AKModel/models.py:776
 msgid "Name of the AK Track"
 msgstr "Name des AK-Tracks"
 
-#: AKModel/models.py:768
+#: AKModel/models.py:783
 msgid "AK Track"
 msgstr "AK-Track"
 
-#: AKModel/models.py:769
+#: AKModel/models.py:784
 msgid "AK Tracks"
 msgstr "AK-Tracks"
 
-#: AKModel/models.py:788
+#: AKModel/models.py:803
 msgid "Name of the Requirement"
 msgstr "Name der Anforderung"
 
-#: AKModel/models.py:794 AKModel/models.py:1338
+#: AKModel/models.py:809 AKModel/models.py:1358
 msgid "AK Requirement"
 msgstr "AK-Anforderung"
 
-#: AKModel/models.py:795
+#: AKModel/models.py:810
 msgid "AK Requirements"
 msgstr "AK-Anforderungen"
 
-#: AKModel/models.py:807
+#: AKModel/models.py:822
 msgid "Name describing the type"
 msgstr "Name, der den Typ beschreibt"
 
-#: AKModel/models.py:813
+#: AKModel/models.py:828
 msgid "AK Type"
 msgstr "AK Typ"
 
-#: AKModel/models.py:814
+#: AKModel/models.py:829
 msgid "AK Types"
 msgstr "AK-Typen"
 
-#: AKModel/models.py:825
+#: AKModel/models.py:840
 msgid "Name of the AK"
 msgstr "Name des AKs"
 
-#: AKModel/models.py:826
+#: AKModel/models.py:842
 msgid "Short Name"
 msgstr "Kurzer Name"
 
-#: AKModel/models.py:827
+#: AKModel/models.py:844
 msgid "Name displayed in the schedule"
 msgstr "Name zur Anzeige im AK-Plan"
 
-#: AKModel/models.py:828
+#: AKModel/models.py:845
 msgid "Description of the AK"
 msgstr "Beschreibung des AKs"
 
-#: AKModel/models.py:830
+#: AKModel/models.py:847
 msgid "Owners"
 msgstr "Leitungen"
 
-#: AKModel/models.py:831
+#: AKModel/models.py:848
 msgid "Those organizing the AK"
 msgstr "Menschen, die den AK organisieren und halten"
 
-#: AKModel/models.py:834
+#: AKModel/models.py:851
 msgid "Link to wiki page"
 msgstr "Link zur Wiki Seite"
 
-#: AKModel/models.py:835
+#: AKModel/models.py:852
 msgid "Protocol Link"
 msgstr "Protokolllink"
 
-#: AKModel/models.py:835
+#: AKModel/models.py:852
 msgid "Link to protocol"
 msgstr "Link zum Protokoll"
 
-#: AKModel/models.py:837
+#: AKModel/models.py:854
 msgid "Category"
 msgstr "Kategorie"
 
-#: AKModel/models.py:838
+#: AKModel/models.py:855
 msgid "Category of the AK"
 msgstr "Kategorie des AKs"
 
-#: AKModel/models.py:839 AKModel/models.py:904
+#: AKModel/models.py:856 AKModel/models.py:921
 msgid "Types"
 msgstr "Typen"
 
-#: AKModel/models.py:840
+#: AKModel/models.py:857
 msgid "This AK is"
 msgstr "Dieser AK ist"
 
-#: AKModel/models.py:841
+#: AKModel/models.py:858
 msgid "Track"
 msgstr "Track"
 
-#: AKModel/models.py:842
+#: AKModel/models.py:859
 msgid "Track the AK belongs to"
 msgstr "Track zu dem der AK gehört"
 
-#: AKModel/models.py:844
+#: AKModel/models.py:861
 msgid "Resolution Intention"
 msgstr "Resolutionsabsicht"
 
-#: AKModel/models.py:845
+#: AKModel/models.py:862
 msgid "Intends to submit a resolution"
 msgstr "Beabsichtigt eine Resolution einzureichen"
 
-#: AKModel/models.py:846
+#: AKModel/models.py:863
 msgid "Present this AK"
 msgstr "AK präsentieren"
 
-#: AKModel/models.py:847
+#: AKModel/models.py:864
 msgid "Present results of this AK"
 msgstr "Die Ergebnisse dieses AKs vorstellen"
 
-#: AKModel/models.py:849 AKModel/models.py:902 AKModel/views/status.py:175
+#: AKModel/models.py:866 AKModel/models.py:919 AKModel/views/status.py:175
 msgid "Requirements"
 msgstr "Anforderungen"
 
-#: AKModel/models.py:850
+#: AKModel/models.py:867
 msgid "AK's Requirements"
 msgstr "Anforderungen des AKs"
 
-#: AKModel/models.py:852
+#: AKModel/models.py:869
 msgid "Conflicting AKs"
 msgstr "AK-Konflikte"
 
-#: AKModel/models.py:853
+#: AKModel/models.py:870
 msgid "AKs that conflict and thus must not take place at the same time"
 msgstr ""
 "AKs, die Konflikte haben und deshalb nicht gleichzeitig stattfinden dürfen"
 
-#: AKModel/models.py:854
+#: AKModel/models.py:871
 msgid "Prerequisite AKs"
 msgstr "Vorausgesetzte AKs"
 
-#: AKModel/models.py:855
+#: AKModel/models.py:872
 msgid "AKs that should precede this AK in the schedule"
 msgstr "AKs die im AK-Plan vor diesem AK stattfinden müssen"
 
-#: AKModel/models.py:857
+#: AKModel/models.py:874
 msgid "Organizational Notes"
 msgstr "Notizen zur Organisation"
 
-#: AKModel/models.py:858
+#: AKModel/models.py:875
 msgid ""
 "Notes to organizers. These are public. For private notes, please use the "
 "button for private messages on the detail page of this AK (after creation/"
@@ -730,299 +738,299 @@ msgstr ""
 "Anmerkungen bitte den Button für Direktnachrichten verwenden (nach dem "
 "Anlegen/Bearbeiten)."
 
-#: AKModel/models.py:861 AKModel/models.py:900
+#: AKModel/models.py:878 AKModel/models.py:917
 msgid "Interest"
 msgstr "Interesse"
 
-#: AKModel/models.py:861
+#: AKModel/models.py:878
 msgid "Expected number of people"
 msgstr "Erwartete Personenzahl"
 
-#: AKModel/models.py:862
+#: AKModel/models.py:879
 msgid "Interest Counter"
 msgstr "Interessenszähler"
 
-#: AKModel/models.py:863
+#: AKModel/models.py:880
 msgid "People who have indicated interest online"
 msgstr "Anzahl Personen, die online Interesse bekundet haben"
 
-#: AKModel/models.py:868
+#: AKModel/models.py:885
 msgid "Export?"
 msgstr "Export?"
 
-#: AKModel/models.py:869
+#: AKModel/models.py:886
 msgid "Include AK in wiki export?"
 msgstr "AK bei Wiki-Export berücksichtigen?"
 
-#: AKModel/models.py:919
+#: AKModel/models.py:936
 msgid "Conflicts"
 msgstr "Konflikte"
 
-#: AKModel/models.py:922
+#: AKModel/models.py:939
 msgid "Prerequisites"
 msgstr "Voraussetzungen"
 
-#: AKModel/models.py:1015
+#: AKModel/models.py:1033
 msgid "Name or number of the room"
 msgstr "Name oder Nummer des Raums"
 
-#: AKModel/models.py:1016
+#: AKModel/models.py:1034
 msgid "Location"
 msgstr "Ort"
 
-#: AKModel/models.py:1017
+#: AKModel/models.py:1035
 msgid "Name or number of the location"
 msgstr "Name oder Nummer des Ortes"
 
-#: AKModel/models.py:1018
+#: AKModel/models.py:1036
 msgid "Capacity"
 msgstr "Kapazität"
 
-#: AKModel/models.py:1019
+#: AKModel/models.py:1037
 msgid "Maximum number of people (-1 for unlimited)."
 msgstr "Maximale Personenzahl (-1 wenn unbeschränkt)."
 
-#: AKModel/models.py:1020
+#: AKModel/models.py:1038
 msgid "Properties"
 msgstr "Eigenschaften"
 
-#: AKModel/models.py:1021
+#: AKModel/models.py:1039
 msgid "AK requirements fulfilled by the room"
 msgstr "AK-Anforderungen, die dieser Raum erfüllt"
 
-#: AKModel/models.py:1028 AKModel/views/status.py:59
+#: AKModel/models.py:1046 AKModel/views/status.py:59
 msgid "Rooms"
 msgstr "Räume"
 
-#: AKModel/models.py:1089
+#: AKModel/models.py:1107
 msgid "AK being mapped"
 msgstr "AK, der zugeordnet wird"
 
-#: AKModel/models.py:1091
+#: AKModel/models.py:1109
 msgid "Room the AK will take place in"
 msgstr "Raum in dem der AK stattfindet"
 
-#: AKModel/models.py:1092 AKModel/models.py:1513
+#: AKModel/models.py:1110 AKModel/models.py:1534
 msgid "Slot Begin"
 msgstr "Beginn des Slots"
 
-#: AKModel/models.py:1092 AKModel/models.py:1513
+#: AKModel/models.py:1110 AKModel/models.py:1534
 msgid "Time and date the slot begins"
 msgstr "Zeit und Datum zu der der AK beginnt"
 
-#: AKModel/models.py:1094
+#: AKModel/models.py:1112
 msgid "Duration"
 msgstr "Dauer"
 
-#: AKModel/models.py:1095
+#: AKModel/models.py:1113
 msgid "Length in hours"
 msgstr "Länge in Stunden"
 
-#: AKModel/models.py:1097
+#: AKModel/models.py:1115
 msgid "Scheduling fixed"
 msgstr "Planung fix"
 
-#: AKModel/models.py:1098
+#: AKModel/models.py:1116
 msgid "Length and time of this AK should not be changed"
 msgstr "Dauer und Zeit dieses AKs sollten nicht verändert werden"
 
-#: AKModel/models.py:1103
+#: AKModel/models.py:1121
 msgid "Last update"
 msgstr "Letzte Aktualisierung"
 
-#: AKModel/models.py:1106
+#: AKModel/models.py:1124
 msgid "AK Slot"
 msgstr "AK-Slot"
 
-#: AKModel/models.py:1107 AKModel/models.py:1331 AKModel/models.py:1366
+#: AKModel/models.py:1125 AKModel/models.py:1351 AKModel/models.py:1386
 msgid "AK Slots"
 msgstr "AK-Slot"
 
-#: AKModel/models.py:1129 AKModel/models.py:1138
+#: AKModel/models.py:1147 AKModel/models.py:1156
 msgid "Not scheduled yet"
 msgstr "Noch nicht geplant"
 
-#: AKModel/models.py:1264
+#: AKModel/models.py:1283
 msgid "AK this message belongs to"
 msgstr "AK zu dem die Nachricht gehört"
 
-#: AKModel/models.py:1265
+#: AKModel/models.py:1284
 msgid "Message text"
 msgstr "Nachrichtentext"
 
-#: AKModel/models.py:1266
+#: AKModel/models.py:1285
 msgid "Message to the organizers. This is not publicly visible."
 msgstr ""
 "Nachricht an die Organisator*innen. Diese ist nicht öffentlich sichtbar."
 
-#: AKModel/models.py:1270
+#: AKModel/models.py:1289
 msgid "Resolved"
 msgstr "Erledigt"
 
-#: AKModel/models.py:1271
+#: AKModel/models.py:1290
 msgid "This message has been resolved (no further action needed)"
 msgstr ""
 "Diese Nachricht wurde vollständig bearbeitet (keine weiteren Aktionen "
 "notwendig)"
 
-#: AKModel/models.py:1274
+#: AKModel/models.py:1293
 msgid "AK Orga Message"
 msgstr "AK-Organachricht"
 
-#: AKModel/models.py:1275
+#: AKModel/models.py:1294
 msgid "AK Orga Messages"
 msgstr "AK-Organachrichten"
 
-#: AKModel/models.py:1292
+#: AKModel/models.py:1312
 msgid "Constraint Violation"
 msgstr "Constraintverletzung"
 
-#: AKModel/models.py:1293
+#: AKModel/models.py:1313
 msgid "Constraint Violations"
 msgstr "Constraintverletzungen"
 
-#: AKModel/models.py:1300
+#: AKModel/models.py:1320
 msgid "Owner has two parallel slots"
 msgstr "Leitung hat zwei Slots parallel"
 
-#: AKModel/models.py:1301
+#: AKModel/models.py:1321
 msgid "AK Slot was scheduled outside the AK's availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeit des AKs platziert"
 
-#: AKModel/models.py:1302
+#: AKModel/models.py:1322
 msgid "Room has two AK slots scheduled at the same time"
 msgstr "Raum hat zwei AK Slots gleichzeitig"
 
-#: AKModel/models.py:1303
+#: AKModel/models.py:1323
 msgid "Room does not satisfy the requirement of the scheduled AK"
 msgstr "Room erfüllt die Anforderungen des platzierten AKs nicht"
 
-#: AKModel/models.py:1304
+#: AKModel/models.py:1324
 msgid "AK Slot is scheduled at the same time as an AK listed as a conflict"
 msgstr ""
 "AK Slot wurde wurde zur gleichen Zeit wie ein Konflikt des AKs platziert"
 
-#: AKModel/models.py:1305
+#: AKModel/models.py:1325
 msgid "AK Slot is scheduled before an AK listed as a prerequisite"
 msgstr "AK Slot wurde vor einem als Voraussetzung gelisteten AK platziert"
 
-#: AKModel/models.py:1307
+#: AKModel/models.py:1327
 msgid ""
 "AK Slot for AK with intention to submit a resolution is scheduled after "
 "resolution deadline"
 msgstr ""
 "AK Slot eines AKs mit Resoabsicht wurde nach der Resodeadline platziert"
 
-#: AKModel/models.py:1308
+#: AKModel/models.py:1328
 msgid "AK Slot in a category is outside that categories availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeiten seiner Kategorie"
 
-#: AKModel/models.py:1309
+#: AKModel/models.py:1329
 msgid "Two AK Slots for the same AK scheduled at the same time"
 msgstr "Zwei AK Slots eines AKs wurden zur selben Zeit platziert"
 
-#: AKModel/models.py:1310
+#: AKModel/models.py:1330
 msgid "Room does not have enough space for interest in scheduled AK Slot"
 msgstr "Room hat nicht genug Platz für das Interesse am geplanten AK-Slot"
 
-#: AKModel/models.py:1311
+#: AKModel/models.py:1331
 msgid "AK Slot is scheduled outside the event's availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeit des Events platziert"
 
-#: AKModel/models.py:1317
+#: AKModel/models.py:1337
 msgid "Warning"
 msgstr "Warnung"
 
-#: AKModel/models.py:1318
+#: AKModel/models.py:1338
 msgid "Violation"
 msgstr "Verletzung"
 
-#: AKModel/models.py:1320
+#: AKModel/models.py:1340
 msgid "Type"
 msgstr "Art"
 
-#: AKModel/models.py:1321
+#: AKModel/models.py:1341
 msgid "Type of violation, i.e. what kind of constraint was violated"
 msgstr "Art der Verletzung, gibt an welche Art Constraint verletzt wurde"
 
-#: AKModel/models.py:1322
+#: AKModel/models.py:1342
 msgid "Level"
 msgstr "Level"
 
-#: AKModel/models.py:1323
+#: AKModel/models.py:1343
 msgid "Severity level of the violation"
 msgstr "Schweregrad der Verletzung"
 
-#: AKModel/models.py:1330
+#: AKModel/models.py:1350
 msgid "AK(s) belonging to this constraint"
 msgstr "AK(s), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1332
+#: AKModel/models.py:1352
 msgid "AK Slot(s) belonging to this constraint"
 msgstr "AK Slot(s), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1334
+#: AKModel/models.py:1354
 msgid "AK Owner belonging to this constraint"
 msgstr "AK Leitung(en), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1336
+#: AKModel/models.py:1356
 msgid "Room belonging to this constraint"
 msgstr "Raum, der zu diesem Constraint gehört"
 
-#: AKModel/models.py:1339
+#: AKModel/models.py:1359
 msgid "AK Requirement belonging to this constraint"
 msgstr "AK Anforderung, die zu diesem Constraint gehört"
 
-#: AKModel/models.py:1341
+#: AKModel/models.py:1361
 msgid "AK Category belonging to this constraint"
 msgstr "AK Kategorie, di zu diesem Constraint gehört"
 
-#: AKModel/models.py:1343
+#: AKModel/models.py:1363
 msgid "Comment"
 msgstr "Kommentar"
 
-#: AKModel/models.py:1343
+#: AKModel/models.py:1363
 msgid "Comment or further details for this violation"
 msgstr "Kommentar oder weitere Details zu dieser Vereletzung"
 
-#: AKModel/models.py:1346
+#: AKModel/models.py:1366
 msgid "Timestamp"
 msgstr "Timestamp"
 
-#: AKModel/models.py:1346
+#: AKModel/models.py:1366
 msgid "Time of creation"
 msgstr "Zeitpunkt der ERstellung"
 
-#: AKModel/models.py:1347
+#: AKModel/models.py:1367
 msgid "Manually Resolved"
 msgstr "Manuell behoben"
 
-#: AKModel/models.py:1348
+#: AKModel/models.py:1368
 msgid "Mark this violation manually as resolved"
 msgstr "Markiere diese Verletzung manuell als behoben"
 
-#: AKModel/models.py:1375 AKModel/templates/admin/AKModel/aks_by_user.html:22
+#: AKModel/models.py:1395 AKModel/templates/admin/AKModel/aks_by_user.html:22
 #: AKModel/templates/admin/AKModel/requirements_overview.html:27
 msgid "Details"
 msgstr "Details"
 
-#: AKModel/models.py:1509
+#: AKModel/models.py:1530
 msgid "Default Slot"
 msgstr "Standardslot"
 
-#: AKModel/models.py:1514
+#: AKModel/models.py:1535
 msgid "Slot End"
 msgstr "Ende des Slots"
 
-#: AKModel/models.py:1514
+#: AKModel/models.py:1535
 msgid "Time and date the slot ends"
 msgstr "Zeit und Datum zu der der Slot endet"
 
-#: AKModel/models.py:1519
+#: AKModel/models.py:1540
 msgid "Primary categories"
 msgstr "Primäre Kategorien"
 
-#: AKModel/models.py:1520
+#: AKModel/models.py:1542
 msgid "Categories that should be assigned to this slot primarily"
 msgstr "Kategorieren, die diesem Slot primär zugewiesen werden sollen"
 
@@ -1241,35 +1249,35 @@ msgstr "AK-CSV-Export"
 msgid "AK JSON Export"
 msgstr "AK-JSON-Export"
 
-#: AKModel/views/ak.py:72
+#: AKModel/views/ak.py:69
 msgid "AK Wiki Export"
 msgstr "AK-Wiki-Export"
 
-#: AKModel/views/ak.py:83 AKModel/views/manage.py:55
+#: AKModel/views/ak.py:80 AKModel/views/manage.py:55
 msgid "Wishes"
 msgstr "Wünsche"
 
-#: AKModel/views/ak.py:95
+#: AKModel/views/ak.py:92
 msgid "Delete AK Orga Messages"
 msgstr "AK-Organachrichten löschen"
 
-#: AKModel/views/ak.py:113
+#: AKModel/views/ak.py:110
 msgid "AK Orga Messages successfully deleted"
 msgstr "AK-Organachrichten erfolgreich gelöscht"
 
-#: AKModel/views/ak.py:125
+#: AKModel/views/ak.py:122
 msgid "Interest of the following AKs will be set to not filled (-1):"
 msgstr "Interesse an den folgenden AKs wird auf nicht ausgefüllt (-1) gesetzt:"
 
-#: AKModel/views/ak.py:126
+#: AKModel/views/ak.py:123
 msgid "Reset of interest in AKs successful."
 msgstr "Interesse an AKs erfolgreich zurückgesetzt."
 
-#: AKModel/views/ak.py:140
+#: AKModel/views/ak.py:137
 msgid "Interest counter of the following AKs will be set to 0:"
 msgstr "Interessensbekundungszähler der folgenden AKs wird auf 0 gesetzt:"
 
-#: AKModel/views/ak.py:141
+#: AKModel/views/ak.py:138
 msgid "AKs' interest counters set back to 0."
 msgstr "Interessenszähler der AKs zurückgesetzt"
 
diff --git a/AKModel/migrations/0063_field_validators.py b/AKModel/migrations/0063_field_validators.py
new file mode 100644
index 0000000000000000000000000000000000000000..347eba289327dd8dc7b8c921f385626c2c725688
--- /dev/null
+++ b/AKModel/migrations/0063_field_validators.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.13 on 2025-03-03 19:59
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('AKModel', '0062_interest_no_history'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='ak',
+            name='name',
+            field=models.CharField(help_text='Name of the AK', max_length=256, validators=[django.core.validators.RegexValidator(inverse_match=True, message='May not contain quotation marks', regex='[\'\\"´`]+'), django.core.validators.RegexValidator(message='Must contain at least one letter or digit', regex='[\\w\\s]+')], verbose_name='Name'),
+        ),
+        migrations.AlterField(
+            model_name='ak',
+            name='short_name',
+            field=models.CharField(blank=True, help_text='Name displayed in the schedule', max_length=64, validators=[django.core.validators.RegexValidator(inverse_match=True, message='May not contain quotation marks', regex='[\'\\"´`]+')], verbose_name='Short Name'),
+        ),
+        migrations.AlterField(
+            model_name='akowner',
+            name='name',
+            field=models.CharField(help_text='Name to identify an AK owner by', max_length=64, validators=[django.core.validators.RegexValidator(inverse_match=True, message='May not contain quotation marks', regex='[\'\\"´`]+'), django.core.validators.RegexValidator(message='Must contain at least one letter or digit', regex='[\\w\\s]+')], verbose_name='Nickname'),
+        ),
+        migrations.AlterField(
+            model_name='historicalak',
+            name='name',
+            field=models.CharField(help_text='Name of the AK', max_length=256, validators=[django.core.validators.RegexValidator(inverse_match=True, message='May not contain quotation marks', regex='[\'\\"´`]+'), django.core.validators.RegexValidator(message='Must contain at least one letter or digit', regex='[\\w\\s]+')], verbose_name='Name'),
+        ),
+        migrations.AlterField(
+            model_name='historicalak',
+            name='short_name',
+            field=models.CharField(blank=True, help_text='Name displayed in the schedule', max_length=64, validators=[django.core.validators.RegexValidator(inverse_match=True, message='May not contain quotation marks', regex='[\'\\"´`]+')], verbose_name='Short Name'),
+        ),
+    ]
diff --git a/AKModel/models.py b/AKModel/models.py
index e6271580dd69e8167a54f31393dd7e8503d298a3..492be77282ce4ac624cb5569b137ed3a3cd4a796 100644
--- a/AKModel/models.py
+++ b/AKModel/models.py
@@ -7,7 +7,9 @@ from datetime import datetime, timedelta
 from typing import Any, Iterable, Generator
 
 from django.db import models, transaction
+from django.core.validators import RegexValidator
 from django.apps import apps
+from django.db import models
 from django.db.models import Count
 from django.urls import reverse_lazy
 from django.utils import timezone
@@ -17,6 +19,16 @@ from simple_history.models import HistoricalRecords
 from timezone_field import TimeZoneField
 
 
+# Custom validators to be used for some of the fields
+# Prevent inclusion of the quotation marks ' " ´ `
+# This may be necessary to prevent javascript issues
+no_quotation_marks_validator = RegexValidator(regex=r"['\"´`]+", inverse_match=True,
+                                              message=_('May not contain quotation marks'))
+# Enforce that the field contains of at least one letter or digit (and not just special characters
+# This prevents issues when autogenerating slugs from that field
+slugable_validator = RegexValidator(regex=r"[\w\s]+", message=_('Must contain at least one letter or digit'))
+
+
 @dataclass
 class OptimizerTimeslot:
     """Class describing a discrete timeslot. Used to interface with an optimizer."""
@@ -132,8 +144,9 @@ class Event(models.Model):
                                          help_text=_('When should AKs with intention to submit a resolution be done?'))
 
     interest_start = models.DateTimeField(verbose_name=_('Interest Window Start'), blank=True, null=True,
-              help_text=
-              _('Opening time for expression of interest. When left blank, no interest indication will be possible.'))
+                                          help_text=
+                                          _('Opening time for expression of interest. When left blank, no interest '
+                                            'indication will be possible.'))
 
     interest_end = models.DateTimeField(verbose_name=_('Interest Window End'), blank=True, null=True,
                                         help_text=_('Closing time for expression of interest.'))
@@ -145,7 +158,7 @@ class Event(models.Model):
     plan_hidden = models.BooleanField(verbose_name=_('Plan Hidden'), help_text=_('Hides plan for non-staff users'),
                                       default=True)
     plan_published_at = models.DateTimeField(verbose_name=_('Plan published at'), blank=True, null=True,
-                                         help_text=_('Timestamp at which the plan was published'))
+                                             help_text=_('Timestamp at which the plan was published'))
 
     base_url = models.URLField(verbose_name=_("Base URL"), help_text=_("Prefix for wiki link construction"), blank=True)
     wiki_export_template_name = models.CharField(verbose_name=_("Wiki Export Template Name"), blank=True, max_length=50)
@@ -159,8 +172,8 @@ class Event(models.Model):
 
 
     contact_email = models.EmailField(verbose_name=_("Contact email address"), blank=True,
-                                        help_text=_("An email address that is displayed on every page "
-                                                    "and can be used for all kinds of questions"))
+                                      help_text=_("An email address that is displayed on every page "
+                                                  "and can be used for all kinds of questions"))
 
     class Meta:
         verbose_name = _('Event')
@@ -191,7 +204,7 @@ class Event(models.Model):
         event = Event.objects.filter(active=True).order_by('start').first()
         # No active event? Return the next event taking place
         if event is None:
-            event = Event.objects.order_by('start').filter(start__gt=datetime.now()).first()
+            event = Event.objects.order_by('start').filter(start__gt=datetime.now().astimezone()).first()
         return event
 
     def get_categories_with_aks(self, wishes_seperately=False,
@@ -646,7 +659,9 @@ class Event(models.Model):
 class AKOwner(models.Model):
     """ An AKOwner describes the person organizing/holding an AK.
     """
-    name = models.CharField(max_length=64, verbose_name=_('Nickname'), help_text=_('Name to identify an AK owner by'))
+    name = models.CharField(max_length=64, verbose_name=_('Nickname'),
+                            validators=[no_quotation_marks_validator, slugable_validator],
+                            help_text=_('Name to identify an AK owner by'))
     slug = models.SlugField(max_length=64, blank=True, verbose_name=_('Slug'), help_text=_('Slug for URL generation'))
     institution = models.CharField(max_length=128, blank=True, verbose_name=_('Institution'), help_text=_('Uni etc.'))
     link = models.URLField(blank=True, verbose_name=_('Web Link'), help_text=_('Link to Homepage'))
@@ -725,8 +740,8 @@ class AKCategory(models.Model):
     description = models.TextField(blank=True, verbose_name=_("Description"),
                                    help_text=_("Short description of this AK Category"))
     present_by_default = models.BooleanField(blank=True, default=True, verbose_name=_("Present by default"),
-                                             help_text=_("Present AKs of this category by default "
-                                                 "if AK owner did not specify whether this AK should be presented?"))
+                                             help_text=_("Present AKs of this category by default if AK owner did not "
+                                                         "specify whether this AK should be presented?"))
 
     event = models.ForeignKey(to=Event, on_delete=models.CASCADE, verbose_name=_('Event'),
                               help_text=_('Associated event'))
@@ -822,8 +837,10 @@ class AKType(models.Model):
 class AK(models.Model):
     """ An AK is a slot-based activity to be scheduled during an event.
     """
-    name = models.CharField(max_length=256, verbose_name=_('Name'), help_text=_('Name of the AK'))
+    name = models.CharField(max_length=256, verbose_name=_('Name'), help_text=_('Name of the AK'),
+                            validators=[no_quotation_marks_validator, slugable_validator])
     short_name = models.CharField(max_length=64, blank=True, verbose_name=_('Short Name'),
+                                  validators=[no_quotation_marks_validator],
                                   help_text=_('Name displayed in the schedule'))
     description = models.TextField(blank=True, verbose_name=_('Description'), help_text=_('Description of the AK'))
 
@@ -837,7 +854,7 @@ class AK(models.Model):
     category = models.ForeignKey(to=AKCategory, on_delete=models.PROTECT, verbose_name=_('Category'),
                                  help_text=_('Category of the AK'))
     types = models.ManyToManyField(to=AKType, blank=True, verbose_name=_('Types'),
-                                          help_text=_("This AK is"))
+                                   help_text=_("This AK is"))
     track = models.ForeignKey(to=AKTrack, blank=True, on_delete=models.SET_NULL, null=True, verbose_name=_('Track'),
                               help_text=_('Track the AK belongs to'))
 
@@ -855,8 +872,8 @@ class AK(models.Model):
                                            help_text=_('AKs that should precede this AK in the schedule'))
 
     notes = models.TextField(blank=True, verbose_name=_('Organizational Notes'), help_text=_(
-        'Notes to organizers. These are public. For private notes, please use the button for private messages '
-        'on the detail page of this AK (after creation/editing).'))
+            'Notes to organizers. These are public. For private notes, please use the button for private messages '
+            'on the detail page of this AK (after creation/editing).'))
 
     interest = models.IntegerField(default=-1, verbose_name=_('Interest'), help_text=_('Expected number of people'))
     interest_counter = models.IntegerField(default=0, verbose_name=_('Interest Counter'),
@@ -997,7 +1014,7 @@ class AK(models.Model):
             return reverse_lazy('submit:ak_detail', kwargs={'event_slug': self.event.slug, 'pk': self.id})
         return self.edit_url
 
-    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
+    def save(self, *args, force_insert=False, force_update=False, using=None, update_fields=None):
         # Auto-Generate Link if not set yet
         if self.link == "":
             link = self.event.base_url + self.name.replace(" ", "_")
@@ -1006,7 +1023,8 @@ class AK(models.Model):
             # Tell Django that we have updated the link field
             if update_fields is not None:
                 update_fields = {"link"}.union(update_fields)
-        super().save(force_insert, force_update, using, update_fields)
+        super().save(*args,
+                     force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
 
 
 class Room(models.Model):
@@ -1161,7 +1179,7 @@ class AKSlot(models.Model):
 
     def overlaps(self, other: "AKSlot"):
         """
-        Check wether two slots overlap
+        Check whether two slots overlap
 
         :param other: second slot to compare with
         :return: true if they overlap, false if not:
@@ -1169,13 +1187,14 @@ class AKSlot(models.Model):
         """
         return self.start < other.end <= self.end or self.start <= other.start < self.end
 
-    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
+    def save(self, *args, force_insert=False, force_update=False, using=None, update_fields=None):
         # Make sure duration is not longer than the event
         if update_fields is None or 'duration' in update_fields:
             event_duration = self.event.end - self.event.start
             event_duration_hours = event_duration.days * 24 + event_duration.seconds // 3600
             self.duration = min(self.duration, event_duration_hours)
-        super().save(force_insert, force_update, using, update_fields)
+        super().save(*args,
+                     force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
 
     def as_json_dict(self) -> dict[str, Any]:
         """Return a json representation of the AK object of this slot.
@@ -1288,6 +1307,7 @@ class ConstraintViolation(models.Model):
     Depending on the type, different fields (references to other models) will be filled. Each violation should always
     be related to an event and at least on other instance of a causing entity
     """
+
     class Meta:
         verbose_name = _('Constraint Violation')
         verbose_name_plural = _('Constraint Violations')
@@ -1304,7 +1324,7 @@ class ConstraintViolation(models.Model):
         AK_CONFLICT_COLLISION = 'acc', _('AK Slot is scheduled at the same time as an AK listed as a conflict')
         AK_BEFORE_PREREQUISITE = 'abp', _('AK Slot is scheduled before an AK listed as a prerequisite')
         AK_AFTER_RESODEADLINE = 'aar', _(
-            'AK Slot for AK with intention to submit a resolution is scheduled after resolution deadline')
+                'AK Slot for AK with intention to submit a resolution is scheduled after resolution deadline')
         AK_CATEGORY_MISMATCH = 'acm', _('AK Slot in a category is outside that categories availabilities')
         AK_SLOT_COLLISION = 'asc', _('Two AK Slots for the same AK scheduled at the same time')
         ROOM_CAPACITY_EXCEEDED = 'rce', _('Room does not have enough space for interest in scheduled AK Slot')
@@ -1505,6 +1525,7 @@ class DefaultSlot(models.Model):
     Model representing a default slot,
     i.e., a prefered slot to use for typical AKs in the schedule to guarantee enough breaks etc.
     """
+
     class Meta:
         verbose_name = _('Default Slot')
         verbose_name_plural = _('Default Slots')
@@ -1517,7 +1538,8 @@ class DefaultSlot(models.Model):
                               help_text=_('Associated event'))
 
     primary_categories = models.ManyToManyField(to=AKCategory, verbose_name=_('Primary categories'), blank=True,
-                                            help_text=_('Categories that should be assigned to this slot primarily'))
+                                                help_text=_(
+                                                        'Categories that should be assigned to this slot primarily'))
 
     @property
     def start_simplified(self) -> str:
diff --git a/AKPlan/views.py b/AKPlan/views.py
index 4123256e0ceb18c0da87526deaea1a0b46b91b39..a3c240a9a46a32937307f8a7381c14aa3b076c4f 100644
--- a/AKPlan/views.py
+++ b/AKPlan/views.py
@@ -1,13 +1,12 @@
-from datetime import timedelta
+from datetime import datetime, timedelta
 
 from django.conf import settings
 from django.shortcuts import redirect
 from django.urls import reverse_lazy
-from django.utils.datetime_safe import datetime
-from django.views.generic import ListView, DetailView
+from django.views.generic import DetailView, ListView
 
-from AKModel.models import AKSlot, Room, AKTrack
 from AKModel.metaviews.admin import FilterByEventSlugMixin
+from AKModel.models import AKSlot, AKTrack, Room
 
 
 class PlanIndexView(FilterByEventSlugMixin, ListView):
@@ -152,7 +151,7 @@ class PlanTrackView(FilterByEventSlugMixin, DetailView):
         context = super().get_context_data(object_list=object_list, **kwargs)
         # Restrict AKSlot list to given track
         # while joining AK, room and category information to reduce the amount of necessary SQL queries
-        context["slots"] = AKSlot.objects.\
-            filter(event=self.event, ak__track=context['track']).\
+        context["slots"] = AKSlot.objects. \
+            filter(event=self.event, ak__track=context['track']). \
             select_related('ak', 'room', 'ak__category')
         return context
diff --git a/AKSubmission/api.py b/AKSubmission/api.py
index 39c3fd460a404735e66d690746c8f65e892b1137..2e82f4e080b1e14c668c048b1ccc3fc0672ec715 100644
--- a/AKSubmission/api.py
+++ b/AKSubmission/api.py
@@ -1,7 +1,8 @@
+from datetime import datetime
+
 from rest_framework import status
 from rest_framework.decorators import api_view
 from rest_framework.response import Response
-from django.utils.datetime_safe import datetime
 
 from AKModel.models import AK
 
diff --git a/AKSubmission/locale/de_DE/LC_MESSAGES/django.po b/AKSubmission/locale/de_DE/LC_MESSAGES/django.po
index f47345a6b052651a9a8e049f95a41be97b463f07..f2c47bb8cc952859563b7df1144ee77d7e036017 100644
--- a/AKSubmission/locale/de_DE/LC_MESSAGES/django.po
+++ b/AKSubmission/locale/de_DE/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-02-27 15:13+0000\n"
+"POT-Creation-Date: 2025-03-04 17:35+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -274,7 +274,7 @@ msgstr "Die Ergebnisse dieses AKs vorstellen"
 msgid "Intends to submit a resolution"
 msgstr "Beabsichtigt eine Resolution einzureichen"
 
-#: AKSubmission/templates/AKSubmission/ak_list.html:6 AKSubmission/views.py:84
+#: AKSubmission/templates/AKSubmission/ak_list.html:6 AKSubmission/views.py:82
 msgid "All AKs"
 msgstr "Alle AKs"
 
@@ -400,78 +400,78 @@ msgstr ""
 msgid "Submit"
 msgstr "Eintragen"
 
-#: AKSubmission/views.py:127
+#: AKSubmission/views.py:125
 msgid "Wishes"
 msgstr "Wünsche"
 
-#: AKSubmission/views.py:127
+#: AKSubmission/views.py:125
 msgid "AKs one would like to have"
 msgstr ""
 "AKs die sich gewünscht wurden, aber bei denen noch nicht klar ist, wer sie "
 "macht. Falls du dir das vorstellen kannst, trag dich einfach ein"
 
-#: AKSubmission/views.py:169
+#: AKSubmission/views.py:167
 msgid "Currently planned AKs"
 msgstr "Aktuell geplante AKs"
 
-#: AKSubmission/views.py:233
+#: AKSubmission/views.py:235
 msgid "AKs with Track"
 msgstr "AK mit Track"
 
-#: AKSubmission/views.py:302
+#: AKSubmission/views.py:305
 msgid "Event inactive. Cannot create or update."
 msgstr "Event inaktiv. Hinzufügen/Bearbeiten nicht möglich."
 
-#: AKSubmission/views.py:327
+#: AKSubmission/views.py:330
 msgid "AK successfully created"
 msgstr "AK erfolgreich angelegt"
 
-#: AKSubmission/views.py:400
+#: AKSubmission/views.py:404
 msgid "AK successfully updated"
 msgstr "AK erfolgreich aktualisiert"
 
-#: AKSubmission/views.py:451
+#: AKSubmission/views.py:455
 #, python-brace-format
 msgid "Added '{owner}' as new owner of '{ak.name}'"
 msgstr "'{owner}' als neue Leitung von '{ak.name}' hinzugefügt"
 
-#: AKSubmission/views.py:555
+#: AKSubmission/views.py:558
 msgid "No user selected"
 msgstr "Keine Person ausgewählt"
 
-#: AKSubmission/views.py:571
+#: AKSubmission/views.py:574
 msgid "Person Info successfully updated"
 msgstr "Personen-Info erfolgreich aktualisiert"
 
-#: AKSubmission/views.py:607
+#: AKSubmission/views.py:610
 msgid "AK Slot successfully added"
 msgstr "AK-Slot erfolgreich angelegt"
 
-#: AKSubmission/views.py:626
+#: AKSubmission/views.py:629
 msgid "You cannot edit a slot that has already been scheduled"
 msgstr "Bereits geplante AK-Slots können nicht mehr bearbeitet werden"
 
-#: AKSubmission/views.py:636
+#: AKSubmission/views.py:639
 msgid "AK Slot successfully updated"
 msgstr "AK-Slot erfolgreich aktualisiert"
 
-#: AKSubmission/views.py:654
+#: AKSubmission/views.py:657
 msgid "You cannot delete a slot that has already been scheduled"
 msgstr "Bereits geplante AK-Slots können nicht mehr gelöscht werden"
 
-#: AKSubmission/views.py:664
+#: AKSubmission/views.py:667
 msgid "AK Slot successfully deleted"
 msgstr "AK-Slot erfolgreich angelegt"
 
-#: AKSubmission/views.py:676
+#: AKSubmission/views.py:679
 msgid "Messages"
 msgstr "Nachrichten"
 
-#: AKSubmission/views.py:686
+#: AKSubmission/views.py:689
 msgid "Delete all messages"
 msgstr "Alle Nachrichten löschen"
 
-#: AKSubmission/views.py:713
+#: AKSubmission/views.py:716
 msgid "Message to organizers successfully saved"
 msgstr "Nachricht an die Organisator*innen erfolgreich gespeichert"
 
diff --git a/AKSubmission/tests.py b/AKSubmission/tests.py
index 8180ea3c10a4b5d28d741467bbc6df4906f25003..fd31454391bbc15ed42ba5e77a1e6da5b04f1461 100644
--- a/AKSubmission/tests.py
+++ b/AKSubmission/tests.py
@@ -1,8 +1,7 @@
-from datetime import timedelta
+from datetime import datetime, timedelta
 
 from django.test import TestCase
 from django.urls import reverse_lazy
-from django.utils.datetime_safe import datetime
 
 from AKModel.models import AK, AKSlot, Event
 from AKModel.tests.test_views import BasicViewTests
@@ -47,8 +46,8 @@ class ModelViewTests(BasicViewTests, TestCase):
          'expected_message': "AK successfully updated"},
         {'view': 'akslot_edit', 'target_view': 'ak_detail', 'kwargs': {'event_slug': 'kif42', 'pk': 5},
          'target_kwargs': {'event_slug': 'kif42', 'pk': 1}, 'expected_message': "AK Slot successfully updated"},
-        {'view': 'akowner_edit', 'target_view': 'submission_overview', 'kwargs': {'event_slug': 'kif42',  'slug': 'a'},
-          'target_kwargs': {'event_slug': 'kif42'}, 'expected_message': "Person Info successfully updated"},
+        {'view': 'akowner_edit', 'target_view': 'submission_overview', 'kwargs': {'event_slug': 'kif42', 'slug': 'a'},
+         'target_kwargs': {'event_slug': 'kif42'}, 'expected_message': "Person Info successfully updated"},
     ]
 
     def test_akslot_edit_delete_prevention(self):
@@ -147,7 +146,8 @@ class ModelViewTests(BasicViewTests, TestCase):
         add_redirect_url = reverse_lazy(f"{self.APP_NAME}:submit_ak", kwargs={'event_slug': 'kif42', 'owner_slug': 'a'})
         response = self.client.post(select_url, {'owner_id': 1})
         self.assertRedirects(response, add_redirect_url, status_code=302, target_status_code=200,
-                    msg_prefix=f"Dispatch redirect to ak submission page failed (should go to {add_redirect_url})")
+                             msg_prefix=f"Dispatch redirect to ak submission page failed "
+                                        f"(should go to {add_redirect_url})")
 
     def test_orga_message_submission(self):
         """
@@ -201,7 +201,8 @@ class ModelViewTests(BasicViewTests, TestCase):
         # Test indication outside of indication window -> HTTP 403, counter not increased
         response = self.client.post(interest_api_url)
         self.assertEqual(response.status_code, 403,
-                    "API end point still reachable even though interest indication window ended ({interest_api_url})")
+                         "API end point still reachable even though interest indication window ended "
+                         "({interest_api_url})")
         self.assertEqual(AK.objects.get(pk=1).interest_counter, ak_interest_counter + 1,
                          "Counter was increased even though interest indication window ended")
 
@@ -243,13 +244,14 @@ class ModelViewTests(BasicViewTests, TestCase):
         Test visibility of requirements field in submission form
         """
         event = Event.get_by_slug('kif42')
-        form = AKSubmissionForm(data={'name': 'Test AK', 'event': event}, instance=None, initial={"event":event})
+        form = AKSubmissionForm(data={'name': 'Test AK', 'event': event}, instance=None, initial={"event": event})
         self.assertIn('requirements', form.fields,
                       msg="Requirements field not present in form even though event has requirements")
 
         event2 = Event.objects.create(name='Event without requirements',
                                       slug='no_req',
-                                      start=datetime.now(), end=datetime.now(),
+                                      start=datetime.now().astimezone(event.timezone),
+                                      end=datetime.now().astimezone(event.timezone),
                                       active=True)
         form2 = AKSubmissionForm(data={'name': 'Test AK', 'event': event2}, instance=None, initial={"event": event2})
         self.assertNotIn('requirements', form2.fields,
@@ -260,13 +262,14 @@ class ModelViewTests(BasicViewTests, TestCase):
         Test visibility of types field in submission form
         """
         event = Event.get_by_slug('kif42')
-        form = AKSubmissionForm(data={'name': 'Test AK', 'event': event}, instance=None, initial={"event":event})
+        form = AKSubmissionForm(data={'name': 'Test AK', 'event': event}, instance=None, initial={"event": event})
         self.assertIn('types', form.fields,
                       msg="Requirements field not present in form even though event has requirements")
 
         event2 = Event.objects.create(name='Event without types',
                                       slug='no_types',
-                                      start=datetime.now(), end=datetime.now(),
+                                      start=datetime.now().astimezone(event.timezone),
+                                      end=datetime.now().astimezone(event.timezone),
                                       active=True)
         form2 = AKSubmissionForm(data={'name': 'Test AK', 'event': event2}, instance=None, initial={"event": event2})
         self.assertNotIn('types', form2.fields,
diff --git a/AKSubmission/views.py b/AKSubmission/views.py
index 5263b875ea21399a5f98d37914403c2f674ec391..3bbffa1f55da2c52e635f6349642de921d6b3cad 100644
--- a/AKSubmission/views.py
+++ b/AKSubmission/views.py
@@ -1,6 +1,6 @@
-from datetime import timedelta
-from math import floor
 from abc import ABC, abstractmethod
+from datetime import datetime, timedelta
+from math import floor
 
 from django.apps import apps
 from django.conf import settings
@@ -8,19 +8,17 @@ from django.contrib import messages
 from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse_lazy
-from django.utils.datetime_safe import datetime
 from django.utils.translation import gettext_lazy as _
 from django.views import View
-from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView
+from django.views.generic import CreateView, DeleteView, DetailView, ListView, TemplateView, UpdateView
 
 from AKModel.availability.models import Availability
 from AKModel.metaviews import status_manager
-from AKModel.metaviews.status import TemplateStatusWidget
-from AKModel.models import AK, AKCategory, AKOwner, AKSlot, AKTrack, AKOrgaMessage
 from AKModel.metaviews.admin import EventSlugMixin, FilterByEventSlugMixin
+from AKModel.metaviews.status import TemplateStatusWidget
+from AKModel.models import AK, AKCategory, AKOrgaMessage, AKOwner, AKSlot, AKTrack
 from AKSubmission.api import ak_interest_indication_active
-from AKSubmission.forms import AKWishForm, AKOwnerForm, AKSubmissionForm, AKDurationForm, AKOrgaMessageForm, \
-    AKForm
+from AKSubmission.forms import AKDurationForm, AKForm, AKOrgaMessageForm, AKOwnerForm, AKSubmissionForm, AKWishForm
 
 
 class SubmissionErrorNotConfiguredView(EventSlugMixin, TemplateView):
@@ -47,7 +45,7 @@ class AKOverviewView(FilterByEventSlugMixin, ListView):
     template_name = "AKSubmission/ak_overview.html"
     wishes_as_category = False
 
-    def filter_aks(self, context, category): # pylint: disable=unused-argument
+    def filter_aks(self, context, category):  # pylint: disable=unused-argument
         """
         Filter which AKs to display based on the given context and category
 
@@ -73,7 +71,7 @@ class AKOverviewView(FilterByEventSlugMixin, ListView):
         """
         return context["categories_with_aks"][0][0].name
 
-    def get_table_title(self, context): # pylint: disable=unused-argument
+    def get_table_title(self, context):  # pylint: disable=unused-argument
         """
         Specify the title above the AK list/table in this view
 
@@ -91,7 +89,7 @@ class AKOverviewView(FilterByEventSlugMixin, ListView):
         redirect to error page if necessary (see :class:`SubmissionErrorNotConfiguredView`)
         """
         self._load_event()
-        self.object_list = self.get_queryset() # pylint: disable=attribute-defined-outside-init
+        self.object_list = self.get_queryset()  # pylint: disable=attribute-defined-outside-init
 
         # No categories yet? Redirect to configuration error page
         if self.object_list.count() == 0:
@@ -124,7 +122,7 @@ class AKOverviewView(FilterByEventSlugMixin, ListView):
 
         if self.wishes_as_category:
             categories_with_aks.append(
-                (AKCategory(name=_("Wishes"), pk=0, description=_("AKs one would like to have")), ak_wishes))
+                    (AKCategory(name=_("Wishes"), pk=0, description=_("AKs one would like to have")), ak_wishes))
 
         context["categories_with_aks"] = categories_with_aks
         context["active_category"] = self.get_active_category_name(context)
@@ -183,10 +181,13 @@ class AKListByCategoryView(AKOverviewView):
 
     This view inherits from :class:`AKOverviewView`, but produces only one list instead of a tabbed one.
     """
+
     def dispatch(self, request, *args, **kwargs):
         # Override dispatching
         # Needed to handle the checking whether the category exists
-        self.category = get_object_or_404(AKCategory, pk=kwargs['category_pk']) # pylint: disable=attribute-defined-outside-init,line-too-long
+        # noinspection PyAttributeOutsideInit
+        # pylint: disable=attribute-defined-outside-init
+        self.category = get_object_or_404(AKCategory, pk=kwargs['category_pk'])
         return super().dispatch(request, *args, **kwargs)
 
     def get_active_category_name(self, context):
@@ -209,11 +210,12 @@ class AKListByTrackView(AKOverviewView):
     This view inherits from :class:`AKOverviewView` and there will be one list per category
     -- but only AKs of a certain given track will be included in them.
     """
+
     def dispatch(self, request, *args, **kwargs):
         # Override dispatching
         # Needed to handle the checking whether the track exists
 
-        self.track = get_object_or_404(AKTrack, pk=kwargs['track_pk']) # pylint: disable=attribute-defined-outside-init
+        self.track = get_object_or_404(AKTrack, pk=kwargs['track_pk'])  # pylint: disable=attribute-defined-outside-init
         return super().dispatch(request, *args, **kwargs)
 
     def filter_aks(self, context, category):
@@ -292,6 +294,7 @@ class EventInactiveRedirectMixin:
     Will add a message explaining why the action was not performed to the user
     and then redirect to start page of the submission component
     """
+
     def get_error_message(self):
         """
         Error message to display after redirect (can be adjusted by this method)
@@ -351,6 +354,7 @@ class AKSubmissionView(AKAndAKWishSubmissionView):
 
     Extends :class:`AKAndAKWishSubmissionView`
     """
+
     def get_initial(self):
         # Load initial values for the form
         # Used to directly add the first owner and the event this AK will belong to
@@ -500,7 +504,6 @@ class AKOwnerDispatchView(ABC, EventSlugMixin, View):
         :rtype: HttpResponseRedirect
         """
 
-
     def post(self, request, *args, **kwargs):
         # This view is solely meant to handle POST requests
         # Perform dispatching based on the submitted owner_id
diff --git a/INSTALL.md b/INSTALL.md
index 5344a998cffe2603aaaffb0583e91fb43e533c38..795ff71a815cd78cf699f829098882c436e522c4 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -10,7 +10,7 @@ setup.
 
 ### System Requirements
 
-* Python 3.10+ incl. development tools
+* Python3.11+ incl. development tools
 * Virtualenv
 * pdflatex & beamer
   class (`texlive-latex-base texlive-latex-recommended texlive-latex-extra texlive-fonts-extra texlive-luatex`)
diff --git a/Utils/check.sh b/Utils/check.sh
index c2e09f5b8852b9a2e70b9c9f6f9e1296c1404f02..a8a9d4b7a9d6e78e7d93cabecb6bd4f36af4f89f 100755
--- a/Utils/check.sh
+++ b/Utils/check.sh
@@ -8,14 +8,21 @@ if [ -z ${VIRTUAL_ENV+x} ]; then
 fi
 
 # enable really all warnings, some of them are silenced by default
-if [[ "$@" == *"--all"* ]]; then
-    export PYTHONWARNINGS=all
-fi
+for arg in "$@"; do
+    if [[ "$arg" == "--all" ]]; then
+        export PYTHONWARNINGS=all
+    fi
+done
 
 # in case of checking production setup
-if [[ "$@" == *"--prod"* ]]; then
-    export DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
-    ./manage.py check --deploy
-fi
+for arg in "$@"; do
+    if [[ "$arg" == "--prod" ]]; then
+      export DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
+      ./manage.py check --deploy
+      ./manage.py makemigrations --dry-run --check
+    fi
+done
 
+# check the setup
 ./manage.py check
+./manage.py makemigrations --dry-run --check
diff --git a/Utils/setup.sh b/Utils/setup.sh
index 6a93207d197e75da2875b31ea8e0e631e114e837..1123bbd8ae707b4b15d2aef6ec33a0ec68a1e2e9 100755
--- a/Utils/setup.sh
+++ b/Utils/setup.sh
@@ -10,7 +10,7 @@ rm -rf venv/
 
 # Setup Python Environment
 # Requires: Virtualenv, appropriate Python installation
-virtualenv venv -p python3.10
+virtualenv venv -p python3.11
 source venv/bin/activate
 pip install --upgrade setuptools pip wheel
 pip install -r requirements.txt
diff --git a/Utils/test.sh b/Utils/test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..ab6dbb2b9f23f3427b773715c5fa4ba1d74c179e
--- /dev/null
+++ b/Utils/test.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Test the AKPlanning setup
+# execute as Utils/test.sh
+
+# activate virtualenv when necessary
+if [ -z ${VIRTUAL_ENV+x} ]; then
+    source venv/bin/activate
+fi
+
+# enable really all warnings, some of them are silenced by default
+for arg in "$@"; do
+    if [[ "$arg" == "--all" ]]; then
+        export PYTHONWARNINGS=all
+    fi
+done
+
+# in case of checking production setup
+for arg in "$@"; do
+    if [[ "$arg" == "--prod" ]]; then
+      export DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
+      ./manage.py test --deploy
+    fi
+done
+
+# run tests
+./manage.py test
diff --git a/requirements.txt b/requirements.txt
index 451feef4db2ee295a38687bc0f96ff1dee637418..9b0938d4a76aff97222757ebd6ac30ac3efef24a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,26 +1,27 @@
-Django==4.2.13
-django-bootstrap5==24.2
-fontawesomefree==6.5.1 # Makes static files (css, fonts) available locally
-django-fontawesome-6==1.0.0.0 # Provides an icon field for models and forms as well as handy shortcuts to render icons
-django-split-settings==1.3.1
-django-timezone-field==6.1.0
-djangorestframework==3.15.1
-django-simple-history==3.5.0
-django-registration-redux==2.13
-django-debug-toolbar==4.3.0
+Django==5.1.6
+django-betterforms==2.0.0
 django-bootstrap-datepicker-plus==5.0.5
-django-tex==1.1.10
-django-csp==3.8
-django-compressor==4.4
+django-bootstrap5==25.1
+django-compressor==4.5.1
+django-debug-toolbar==5.0.1
+django-fontawesome-6==1.0.0.0  # Provides an icon field for models and forms as well as handy shortcuts to render icons
 django-libsass==0.9
-django-betterforms==2.0.0
-mysqlclient==2.2.0  # for production deployment
-tzdata==2024.1
+django-registration-redux==2.13
+django-simple-history==3.8.0
+django-split-settings==1.3.2
+django-tex==1.1.10
+django-timezone-field==7.1
+django_csp==3.8
+djangorestframework==3.15.2
+
+fontawesomefree==6.6.0  # Makes static files (css, fonts) available locally
+mysqlclient==2.2.7  # for production deployment
+tzdata==2025.1
 
 # Documentation
-sphinxcontrib-django==2.5
+Sphinx==8.2.3
+sphinx-rtd-theme==3.0.2
 sphinxcontrib-apidoc==0.5.0
+sphinxcontrib-django==2.5.0
 recommonmark==0.7.1
 django-docs==0.3.3
-sphinx-rtd-theme==2.0.0
-sphinx==7.3.7