diff --git a/biscuit/core/__init__.py b/biscuit/core/__init__.py
index ef696833a713e9bad35ffaeff41cdf46aa7ebd4e..4d87b04132c9610b1f3a2a340eb74cc9ede8ceb3 100644
--- a/biscuit/core/__init__.py
+++ b/biscuit/core/__init__.py
@@ -1,8 +1,8 @@
 import pkg_resources
 
 try:
-    __version__ = pkg_resources.get_distribution('BiscuIT-ng').version
+    __version__ = pkg_resources.get_distribution("BiscuIT-ng").version
 except Exception:
-    __version__ = 'unknown'
+    __version__ = "unknown"
 
-default_app_config = 'biscuit.core.apps.CoreConfig'
+default_app_config = "biscuit.core.apps.CoreConfig"
diff --git a/biscuit/core/anonymizers.py b/biscuit/core/anonymizers.py
index 9a063a819a0f5dac62353c5e2a5dfd1a6ca088a3..3a9094c4140347ac5b738402ef5731582d064a2e 100644
--- a/biscuit/core/anonymizers.py
+++ b/biscuit/core/anonymizers.py
@@ -7,20 +7,20 @@ class PersonAnonymizer(BaseAnonymizer):
     model = Person
 
     attributes = [
-        ('first_name', faker.first_name),
-        ('last_name', faker.last_name),
-        ('additional_name', ''),
-        ('short_name', lambda **kwargs: faker.pystr(min_chars=3, max_chars=5, **kwargs)),
-        ('street', faker.street_name),
-        ('housenumber', faker.building_number),
-        ('postal_code', faker.postcode),
-        ('place', faker.city),
-        ('phone_number', ''),
-        ('mobile_number', ''),
-        ('email', faker.email),
+        ("first_name", faker.first_name),
+        ("last_name", faker.last_name),
+        ("additional_name", ""),
+        ("short_name", lambda **kwargs: faker.pystr(min_chars=3, max_chars=5, **kwargs)),
+        ("street", faker.street_name),
+        ("housenumber", faker.building_number),
+        ("postal_code", faker.postcode),
+        ("place", faker.city),
+        ("phone_number", ""),
+        ("mobile_number", ""),
+        ("email", faker.email),
         (
-            'date_of_birth',
+            "date_of_birth",
             lambda **kwargs: faker.date_of_birth(minimum_age=8, maximum_age=66, **kwargs),
         ),
-        ('photo', ''),
+        ("photo", ""),
     ]
diff --git a/biscuit/core/apps.py b/biscuit/core/apps.py
index ef62cfb3085fa7d763f4506bc94613fcc77c7c53..5c5b3093b16309d23ffa0a985e7458fe356b800b 100644
--- a/biscuit/core/apps.py
+++ b/biscuit/core/apps.py
@@ -5,9 +5,9 @@ from .signals import clean_scss
 
 
 class CoreConfig(AppConfig):
-    name = 'biscuit.core'
-    verbose_name = 'BiscuIT - The Free School Information System'
+    name = "biscuit.core"
+    verbose_name = "BiscuIT - The Free School Information System"
 
     def ready(self) -> None:
         clean_scss()
-        post_save.connect(clean_scss, sender=apps.get_model('dbsettings', 'Setting'))
+        post_save.connect(clean_scss, sender=apps.get_model("dbsettings", "Setting"))
diff --git a/biscuit/core/cronjobs.py b/biscuit/core/cronjobs.py
index 4c9d81ebb412fd986830f0bbef9dd03e196d2bb4..66e6c069c90ac6047ce3d10b867d1297a84ac61d 100644
--- a/biscuit/core/cronjobs.py
+++ b/biscuit/core/cronjobs.py
@@ -10,8 +10,8 @@ class Backup(CronJobBase):
     schedule = Schedule(
         run_at_times=RUN_AT_TIMES, retry_after_failure_mins=RETRY_AFTER_FAILURE_MINS
     )
-    code = 'biscuit.core.Backup'
+    code = "biscuit.core.Backup"
 
     def do(self):
-        management.call_command('dbbackup', '-z')
-        management.call_command('mediabackup', '-z')
+        management.call_command("dbbackup", "-z")
+        management.call_command("mediabackup", "-z")
diff --git a/biscuit/core/forms.py b/biscuit/core/forms.py
index 119730401b574eebef1657b3700c34f16d4b4f28..e032df5f7a53febfa5ef3b2222390a9f11f5d83f 100644
--- a/biscuit/core/forms.py
+++ b/biscuit/core/forms.py
@@ -9,36 +9,36 @@ from .models import Person, Group, School, SchoolTerm
 class PersonAccountForm(forms.ModelForm):
     class Meta:
         model = Person
-        fields = ['last_name', 'first_name', 'user']
-        widgets = {'user': Select2Widget}
+        fields = ["last_name", "first_name", "user"]
+        widgets = {"user": Select2Widget}
 
     new_user = forms.CharField(required=False)
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        self.fields['first_name'].disabled = True
-        self.fields['last_name'].disabled = True
+        self.fields["first_name"].disabled = True
+        self.fields["last_name"].disabled = True
 
     def clean(self) -> None:
         User = get_user_model()
 
-        if self.cleaned_data.get('new_user', None):
-            if self.cleaned_data.get('user', None):
+        if self.cleaned_data.get("new_user", None):
+            if self.cleaned_data.get("user", None):
                 self.add_error(
-                    'new_user',
-                    _('You cannot set a new username when also selecting an existing user.'),
+                    "new_user",
+                    _("You cannot set a new username when also selecting an existing user."),
                 )
-            elif User.objects.filter(username=self.cleaned_data['new_user']).exists():
-                self.add_error('new_user', _('This username is already in use.'))
+            elif User.objects.filter(username=self.cleaned_data["new_user"]).exists():
+                self.add_error("new_user", _("This username is already in use."))
             else:
                 new_user_obj = User.objects.create_user(
-                    self.cleaned_data['new_user'],
+                    self.cleaned_data["new_user"],
                     self.instance.email,
                     first_name=self.instance.first_name,
                     last_name=self.instance.last_name,
                 )
 
-                self.cleaned_data['user'] = new_user_obj
+                self.cleaned_data["user"] = new_user_obj
 
 
 PersonsAccountsFormSet = forms.modelformset_factory(
@@ -50,73 +50,73 @@ class EditPersonForm(forms.ModelForm):
     class Meta:
         model = Person
         fields = [
-            'user',
-            'is_active',
-            'first_name',
-            'last_name',
-            'additional_name',
-            'short_name',
-            'street',
-            'housenumber',
-            'postal_code',
-            'place',
-            'phone_number',
-            'mobile_number',
-            'email',
-            'date_of_birth',
-            'sex',
-            'photo',
-            'photo_cropping',
+            "user",
+            "is_active",
+            "first_name",
+            "last_name",
+            "additional_name",
+            "short_name",
+            "street",
+            "housenumber",
+            "postal_code",
+            "place",
+            "phone_number",
+            "mobile_number",
+            "email",
+            "date_of_birth",
+            "sex",
+            "photo",
+            "photo_cropping",
         ]
-        widgets = {'user': Select2Widget}
+        widgets = {"user": Select2Widget}
 
     new_user = forms.CharField(
-        required=False, label=_('New user'), help_text=_('Create a new account')
+        required=False, label=_("New user"), help_text=_("Create a new account")
     )
 
     def clean(self) -> None:
         User = get_user_model()
 
-        if self.cleaned_data.get('new_user', None):
-            if self.cleaned_data.get('user', None):
+        if self.cleaned_data.get("new_user", None):
+            if self.cleaned_data.get("user", None):
                 self.add_error(
-                    'new_user',
-                    _('You cannot set a new username when also selecting an existing user.'),
+                    "new_user",
+                    _("You cannot set a new username when also selecting an existing user."),
                 )
-            elif User.objects.filter(username=self.cleaned_data['new_user']).exists():
-                self.add_error('new_user', _('This username is already in use.'))
+            elif User.objects.filter(username=self.cleaned_data["new_user"]).exists():
+                self.add_error("new_user", _("This username is already in use."))
             else:
                 new_user_obj = User.objects.create_user(
-                    self.cleaned_data['new_user'],
+                    self.cleaned_data["new_user"],
                     self.instance.email,
                     first_name=self.instance.first_name,
                     last_name=self.instance.last_name,
                 )
 
-                self.cleaned_data['user'] = new_user_obj
+                self.cleaned_data["user"] = new_user_obj
 
 
 class EditGroupForm(forms.ModelForm):
     class Meta:
         model = Group
-        fields = ['name', 'short_name', 'members', 'owners', 'parent_groups']
+        fields = ["name", "short_name", "members", "owners", "parent_groups"]
         widgets = {
-            'members': ModelSelect2MultipleWidget(
+            "members": ModelSelect2MultipleWidget(
                 search_fields=[
-                    'first_name__icontains',
-                    'last_name__icontains',
-                    'short_name__icontains',
+                    "first_name__icontains",
+                    "last_name__icontains",
+                    "short_name__icontains",
                 ]
             ),
-            'owners': ModelSelect2MultipleWidget(
+            "owners": ModelSelect2MultipleWidget(
                 search_fields=[
-                    'first_name__icontains',
-                    'last_name__icontains',
-                    'short_name__icontains',
+                    "first_name__icontains",
+                    "last_name__icontains",
+                    "short_name__icontains",
                 ]
             ),
-            'parent_groups': ModelSelect2MultipleWidget(
-                search_fields=['name__icontains', 'short_name__icontains']
+            "parent_groups": ModelSelect2MultipleWidget(
+                search_fields=["name__icontains", "short_name__icontains"]
             ),
         }
 
@@ -124,10 +124,10 @@ class EditGroupForm(forms.ModelForm):
 class EditSchoolForm(forms.ModelForm):
     class Meta:
         model = School
-        fields = ['name', 'name_official', 'logo', 'logo_cropping']
+        fields = ["name", "name_official", "logo", "logo_cropping"]
 
 
 class EditTermForm(forms.ModelForm):
     class Meta:
         model = SchoolTerm
-        fields = ['caption', 'date_start', 'date_end']
+        fields = ["caption", "date_start", "date_end"]
diff --git a/biscuit/core/menus.py b/biscuit/core/menus.py
index f4afc55773b106cb26b4fcc408be9ebc061f4149..cbb745d053bb6565aca7fad34f332434c5612af2 100644
--- a/biscuit/core/menus.py
+++ b/biscuit/core/menus.py
@@ -2,125 +2,125 @@ from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
 
 MENUS = {
-    'NAV_MENU_CORE': [
+    "NAV_MENU_CORE": [
         {
-            'name': _('Account'),
-            'url': '#',
-            'root': True,
-            'submenu': [
+            "name": _("Account"),
+            "url": "#",
+            "root": True,
+            "submenu": [
                 {
-                    'name': _('Stop impersonation'),
-                    'url': 'impersonate-stop',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'biscuit.core.util.core_helpers.is_impersonate',
+                    "name": _("Stop impersonation"),
+                    "url": "impersonate-stop",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "biscuit.core.util.core_helpers.is_impersonate",
                     ],
                 },
                 {
-                    'name': _('Login'),
-                    'url': settings.LOGIN_URL,
-                    'validators': ['menu_generator.validators.is_anonymous'],
+                    "name": _("Login"),
+                    "url": settings.LOGIN_URL,
+                    "validators": ["menu_generator.validators.is_anonymous"],
                 },
                 {
-                    'name': _('Logout'),
-                    'url': 'logout',
-                    'validators': ['menu_generator.validators.is_authenticated'],
+                    "name": _("Logout"),
+                    "url": "logout",
+                    "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
-                    'name': _('Two factor auth'),
-                    'url': 'two_factor:profile',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        lambda request: 'two_factor' in settings.INSTALLED_APPS,
+                    "name": _("Two factor auth"),
+                    "url": "two_factor:profile",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        lambda request: "two_factor" in settings.INSTALLED_APPS,
                     ],
                 },
             ],
         },
         {
-            'name': _('Admin'),
-            'url': '#',
-            'validators': [
-                'menu_generator.validators.is_authenticated',
-                'menu_generator.validators.is_superuser',
+            "name": _("Admin"),
+            "url": "#",
+            "validators": [
+                "menu_generator.validators.is_authenticated",
+                "menu_generator.validators.is_superuser",
             ],
-            'submenu': [
+            "submenu": [
                 {
-                    'name': _('Data management'),
-                    'url': 'data_management',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'menu_generator.validators.is_superuser',
+                    "name": _("Data management"),
+                    "url": "data_management",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "menu_generator.validators.is_superuser",
                     ],
                 },
                 {
-                    'name': _('System status'),
-                    'url': 'system_status',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'menu_generator.validators.is_superuser',
+                    "name": _("System status"),
+                    "url": "system_status",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "menu_generator.validators.is_superuser",
                     ],
                 },
                 {
-                    'name': _('Impersonation'),
-                    'url': 'impersonate-list',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'menu_generator.validators.is_superuser',
+                    "name": _("Impersonation"),
+                    "url": "impersonate-list",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "menu_generator.validators.is_superuser",
                     ],
                 },
                 {
-                    'name': _('Manage school'),
-                    'url': 'school_management',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'menu_generator.validators.is_superuser',
+                    "name": _("Manage school"),
+                    "url": "school_management",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "menu_generator.validators.is_superuser",
                     ],
                 },
             ],
         },
         {
-            'name': _('People'),
-            'url': '#',
-            'root': True,
-            'validators': [
-                'menu_generator.validators.is_authenticated',
-                'biscuit.core.util.core_helpers.has_person',
+            "name": _("People"),
+            "url": "#",
+            "root": True,
+            "validators": [
+                "menu_generator.validators.is_authenticated",
+                "biscuit.core.util.core_helpers.has_person",
             ],
-            'submenu': [
+            "submenu": [
                 {
-                    'name': _('Persons'),
-                    'url': 'persons',
-                    'validators': ['menu_generator.validators.is_authenticated'],
+                    "name": _("Persons"),
+                    "url": "persons",
+                    "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
-                    'name': _('Groups'),
-                    'url': 'groups',
-                    'validators': ['menu_generator.validators.is_authenticated'],
+                    "name": _("Groups"),
+                    "url": "groups",
+                    "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
-                    'name': _('Persons and accounts'),
-                    'url': 'persons_accounts',
-                    'validators': [
-                        'menu_generator.validators.is_authenticated',
-                        'menu_generator.validators.is_superuser',
+                    "name": _("Persons and accounts"),
+                    "url": "persons_accounts",
+                    "validators": [
+                        "menu_generator.validators.is_authenticated",
+                        "menu_generator.validators.is_superuser",
                     ],
                 },
             ],
         },
     ],
-    'FOOTER_MENU_CORE': [
+    "FOOTER_MENU_CORE": [
         {
-            'name': _('BiscuIT Software'),
-            'url': '#',
-            'submenu': [
-                {'name': _('Website'), 'url': 'https://biscuit.edugit.org/'},
-                {'name': 'Teckids e.V.', 'url': 'https://www.teckids.org/'},
+            "name": _("BiscuIT Software"),
+            "url": "#",
+            "submenu": [
+                {"name": _("Website"), "url": "https://biscuit.edugit.org/"},
+                {"name": "Teckids e.V.", "url": "https://www.teckids.org/"},
             ],
         },
     ],
-    'DATA_MANAGEMENT_MENU': [],
-    'SCHOOL_MANAGEMENT_MENU': [
-        {'name': _('Edit school information'), 'url': 'edit_school_information',},
-        {'name': _('Edit school term'), 'url': 'edit_school_term',},
+    "DATA_MANAGEMENT_MENU": [],
+    "SCHOOL_MANAGEMENT_MENU": [
+        {"name": _("Edit school information"), "url": "edit_school_information",},
+        {"name": _("Edit school term"), "url": "edit_school_term",},
     ],
 }
diff --git a/biscuit/core/mixins.py b/biscuit/core/mixins.py
index a5d535ac2cedcbd76e25e8c042d235fbc15b28e8..6db9ffe40229c36ffb51292925cfe62ad10f2408 100644
--- a/biscuit/core/mixins.py
+++ b/biscuit/core/mixins.py
@@ -46,11 +46,11 @@ class ExtensibleModel(object):
             if name.isidentifier():
                 prop_name = name
             else:
-                raise ValueError('%s is not a valid name.' % name)
+                raise ValueError("%s is not a valid name." % name)
 
         # Verify that property name does not clash with other names in the class
         if hasattr(cls, prop_name):
-            raise ValueError('%s already used.' % prop_name)
+            raise ValueError("%s already used." % prop_name)
 
         # Add function wrapped in property decorator if we got here
         setattr(cls, prop_name, obj)
@@ -80,4 +80,4 @@ class CRUDMixin(models.Model):
 
         return CRUDEvent.objects.filter(
             object_id=self.pk, content_type=content_type
-        ).select_related('user')
+        ).select_related("user")
diff --git a/biscuit/core/models.py b/biscuit/core/models.py
index a659136d97cc584643eae3cc715166870b678159..eab46395fcea5d7681ae5fa1a2c90ba99437c72e 100644
--- a/biscuit/core/models.py
+++ b/biscuit/core/models.py
@@ -12,17 +12,17 @@ from .mixins import ExtensibleModel
 
 
 class ThemeSettings(dbsettings.Group):
-    colour_primary = dbsettings.StringValue(default='#007bff')
-    colour_secondary = dbsettings.StringValue(default='#6c757d')
-    colour_success = dbsettings.StringValue(default='#28a745')
-    colour_info = dbsettings.StringValue(default='#17a2b8')
-    colour_warning = dbsettings.StringValue(default='#ffc107')
-    colour_danger = dbsettings.StringValue(default='#dc3545')
-    colour_light = dbsettings.StringValue(default='#f8f9fa')
-    colour_dark = dbsettings.StringValue(default='#343a40')
+    colour_primary = dbsettings.StringValue(default="#007bff")
+    colour_secondary = dbsettings.StringValue(default="#6c757d")
+    colour_success = dbsettings.StringValue(default="#28a745")
+    colour_info = dbsettings.StringValue(default="#17a2b8")
+    colour_warning = dbsettings.StringValue(default="#ffc107")
+    colour_danger = dbsettings.StringValue(default="#dc3545")
+    colour_light = dbsettings.StringValue(default="#f8f9fa")
+    colour_dark = dbsettings.StringValue(default="#343a40")
 
 
-theme_settings = ThemeSettings('Global theme settings')
+theme_settings = ThemeSettings("Global theme settings")
 
 
 class School(models.Model):
@@ -32,22 +32,22 @@ class School(models.Model):
     currently logged-in user.
     """
 
-    name = models.CharField(verbose_name=_('Name'), max_length=30)
+    name = models.CharField(verbose_name=_("Name"), max_length=30)
     name_official = models.CharField(
-        verbose_name=_('Official name'),
+        verbose_name=_("Official name"),
         max_length=200,
-        help_text=_('Official name of the school, e.g. as given by supervisory authority'),
+        help_text=_("Official name of the school, e.g. as given by supervisory authority"),
     )
 
-    logo = ImageCropField(verbose_name=_('School logo'), blank=True, null=True)
-    logo_cropping = ImageRatioField('logo', '600x600', size_warning=True)
+    logo = ImageCropField(verbose_name=_("School logo"), blank=True, null=True)
+    logo_cropping = ImageRatioField("logo", "600x600", size_warning=True)
 
     @property
     def current_term(self):
         return SchoolTerm.objects.get(current=True)
 
     class Meta:
-        ordering = ['name', 'name_official']
+        ordering = ["name", "name_official"]
 
 
 class SchoolTerm(models.Model):
@@ -55,10 +55,10 @@ class SchoolTerm(models.Model):
     be linked to.
     """
 
-    caption = models.CharField(verbose_name=_('Visible caption of the term'), max_length=30)
+    caption = models.CharField(verbose_name=_("Visible caption of the term"), max_length=30)
 
-    date_start = models.DateField(verbose_name=_('Effective start date of term'), null=True)
-    date_end = models.DateField(verbose_name=_('Effective end date of term'), null=True)
+    date_start = models.DateField(verbose_name=_("Effective start date of term"), null=True)
+    date_end = models.DateField(verbose_name=_("Effective end date of term"), null=True)
 
     current = models.NullBooleanField(default=None, unique=True)
 
@@ -74,43 +74,43 @@ class Person(models.Model, ExtensibleModel):
     """
 
     class Meta:
-        ordering = ['last_name', 'first_name']
+        ordering = ["last_name", "first_name"]
 
-    SEX_CHOICES = [('f', _('female')), ('m', _('male'))]
+    SEX_CHOICES = [("f", _("female")), ("m", _("male"))]
 
     user = models.OneToOneField(
-        get_user_model(), on_delete=models.SET_NULL, blank=True, null=True, related_name='person'
+        get_user_model(), on_delete=models.SET_NULL, blank=True, null=True, related_name="person"
     )
-    is_active = models.BooleanField(verbose_name=_('Is person active?'), default=True)
+    is_active = models.BooleanField(verbose_name=_("Is person active?"), default=True)
 
-    first_name = models.CharField(verbose_name=_('First name'), max_length=30)
-    last_name = models.CharField(verbose_name=_('Last name'), max_length=30)
+    first_name = models.CharField(verbose_name=_("First name"), max_length=30)
+    last_name = models.CharField(verbose_name=_("Last name"), max_length=30)
     additional_name = models.CharField(
-        verbose_name=_('Additional name(s)'), max_length=30, blank=True
+        verbose_name=_("Additional name(s)"), max_length=30, blank=True
     )
 
     short_name = models.CharField(
-        verbose_name=_('Short name'), max_length=5, blank=True, null=True, unique=True
+        verbose_name=_("Short name"), max_length=5, blank=True, null=True, unique=True
     )
 
-    street = models.CharField(verbose_name=_('Street'), max_length=30, blank=True)
-    housenumber = models.CharField(verbose_name=_('Street number'), max_length=10, blank=True)
-    postal_code = models.CharField(verbose_name=_('Postal code'), max_length=5, blank=True)
-    place = models.CharField(verbose_name=_('Place'), max_length=30, blank=True)
+    street = models.CharField(verbose_name=_("Street"), max_length=30, blank=True)
+    housenumber = models.CharField(verbose_name=_("Street number"), max_length=10, blank=True)
+    postal_code = models.CharField(verbose_name=_("Postal code"), max_length=5, blank=True)
+    place = models.CharField(verbose_name=_("Place"), max_length=30, blank=True)
 
-    phone_number = PhoneNumberField(verbose_name=_('Home phone'), blank=True)
-    mobile_number = PhoneNumberField(verbose_name=_('Mobile phone'), blank=True)
+    phone_number = PhoneNumberField(verbose_name=_("Home phone"), blank=True)
+    mobile_number = PhoneNumberField(verbose_name=_("Mobile phone"), blank=True)
 
-    email = models.EmailField(verbose_name=_('E-mail address'), blank=True)
+    email = models.EmailField(verbose_name=_("E-mail address"), blank=True)
 
-    date_of_birth = models.DateField(verbose_name=_('Date of birth'), blank=True, null=True)
-    sex = models.CharField(verbose_name=_('Sex'), max_length=1, choices=SEX_CHOICES, blank=True)
+    date_of_birth = models.DateField(verbose_name=_("Date of birth"), blank=True, null=True)
+    sex = models.CharField(verbose_name=_("Sex"), max_length=1, choices=SEX_CHOICES, blank=True)
 
-    photo = ImageCropField(verbose_name=_('Photo'), blank=True, null=True)
-    photo_cropping = ImageRatioField('photo', '600x800', size_warning=True)
+    photo = ImageCropField(verbose_name=_("Photo"), blank=True, null=True)
+    photo_cropping = ImageRatioField("photo", "600x800", size_warning=True)
 
     import_ref = models.CharField(
-        verbose_name=_('Reference ID of import source'),
+        verbose_name=_("Reference ID of import source"),
         max_length=64,
         blank=True,
         null=True,
@@ -119,10 +119,10 @@ class Person(models.Model, ExtensibleModel):
     )
 
     guardians = models.ManyToManyField(
-        'self', verbose_name=_('Guardians / Parents'), symmetrical=False, related_name='children'
+        "self", verbose_name=_("Guardians / Parents"), symmetrical=False, related_name="children"
     )
 
-    primary_group = models.ForeignKey('Group', models.SET_NULL, null=True)
+    primary_group = models.ForeignKey("Group", models.SET_NULL, null=True)
 
     @property
     def primary_group_short_name(self) -> Optional[str]:
@@ -141,12 +141,12 @@ class Person(models.Model, ExtensibleModel):
         if it can't find one.
         """
 
-        group, created = Group.objects.get_or_create(short_name=value, defaults={'name': value})
+        group, created = Group.objects.get_or_create(short_name=value, defaults={"name": value})
         self.primary_group = group
 
     @property
     def full_name(self) -> str:
-        return '%s, %s' % (self.last_name, self.first_name)
+        return "%s, %s" % (self.last_name, self.first_name)
 
     def __str__(self) -> str:
         return self.full_name
@@ -158,21 +158,21 @@ class Group(models.Model, ExtensibleModel):
     """
 
     class Meta:
-        ordering = ['short_name', 'name']
+        ordering = ["short_name", "name"]
 
-    name = models.CharField(verbose_name=_('Long name of group'), max_length=60, unique=True)
-    short_name = models.CharField(verbose_name=_('Short name of group'), max_length=16, unique=True)
+    name = models.CharField(verbose_name=_("Long name of group"), max_length=60, unique=True)
+    short_name = models.CharField(verbose_name=_("Short name of group"), max_length=16, unique=True)
 
-    members = models.ManyToManyField('Person', related_name='member_of')
-    owners = models.ManyToManyField('Person', related_name='owner_of')
+    members = models.ManyToManyField("Person", related_name="member_of")
+    owners = models.ManyToManyField("Person", related_name="owner_of")
 
     parent_groups = models.ManyToManyField(
-        'self',
-        related_name='child_groups',
+        "self",
+        related_name="child_groups",
         symmetrical=False,
-        verbose_name=_('Parent groups'),
+        verbose_name=_("Parent groups"),
         blank=True,
     )
 
     def __str__(self) -> str:
-        return '%s (%s)' % (self.name, self.short_name)
+        return "%s (%s)" % (self.name, self.short_name)
diff --git a/biscuit/core/settings.py b/biscuit/core/settings.py
index 66441e7143637d4f45d57cb76639599f23bd76ed..b265e7de3903140c7f004b04eac8ccd7048da200 100644
--- a/biscuit/core/settings.py
+++ b/biscuit/core/settings.py
@@ -9,14 +9,14 @@ from easy_thumbnails.conf import Settings as thumbnail_settings
 
 from .util.core_helpers import get_app_packages
 
-ENVVAR_PREFIX_FOR_DYNACONF = 'BISCUIT'
-DIRS_FOR_DYNACONF = ['/etc/biscuit']
+ENVVAR_PREFIX_FOR_DYNACONF = "BISCUIT"
+DIRS_FOR_DYNACONF = ["/etc/biscuit"]
 
 SETTINGS_FILE_FOR_DYNACONF = []
 for directory in DIRS_FOR_DYNACONF:
-    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, '*.ini'))
-    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, '*.yaml'))
-    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, '*.toml'))
+    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, "*.ini"))
+    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, "*.yaml"))
+    SETTINGS_FILE_FOR_DYNACONF += glob(os.path.join(directory, "*.toml"))
 
 _settings = LazySettings(
     ENVVAR_PREFIX_FOR_DYNACONF=ENVVAR_PREFIX_FOR_DYNACONF,
@@ -27,136 +27,136 @@ _settings = LazySettings(
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 # SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = _settings.get('secret_key', 'DoNotUseInProduction')
+SECRET_KEY = _settings.get("secret_key", "DoNotUseInProduction")
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = _settings.get('maintenance.debug', False)
-INTERNAL_IPS = _settings.get('maintenance.internal_ips', [])
+DEBUG = _settings.get("maintenance.debug", False)
+INTERNAL_IPS = _settings.get("maintenance.internal_ips", [])
 DEBUG_TOOLBAR_CONFIG = {
-    'RENDER_PANELS': True,
-    'SHOW_COLLAPSED': True,
-    'JQUERY_URL': '',
-    'SHOW_TOOLBAR_CALLBACK': 'biscuit.core.util.core_helpers.dt_show_toolbar',
+    "RENDER_PANELS": True,
+    "SHOW_COLLAPSED": True,
+    "JQUERY_URL": "",
+    "SHOW_TOOLBAR_CALLBACK": "biscuit.core.util.core_helpers.dt_show_toolbar",
 }
 
-ALLOWED_HOSTS = _settings.get('http.allowed_hosts', [])
+ALLOWED_HOSTS = _settings.get("http.allowed_hosts", [])
 
 # Application definition
 INSTALLED_APPS = [
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.messages',
-    'django.contrib.staticfiles',
-    'django_global_request',
-    'settings_context_processor',
-    'sass_processor',
-    'easyaudit',
-    'dbbackup',
-    'dbsettings',
-    'django_cron',
-    'bootstrap4',
-    'fa',
-    'django_any_js',
-    'django_yarnpkg',
-    'django_tables2',
-    'easy_thumbnails',
-    'image_cropping',
-    'maintenance_mode',
-    'menu_generator',
-    'phonenumber_field',
-    'debug_toolbar',
-    'django_select2',
-    'hattori',
-    'django_otp.plugins.otp_totp',
-    'django_otp.plugins.otp_static',
-    'django_otp',
-    'otp_yubikey',
-    'biscuit.core',
-    'impersonate',
-    'two_factor',
+    "django.contrib.admin",
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.messages",
+    "django.contrib.staticfiles",
+    "django_global_request",
+    "settings_context_processor",
+    "sass_processor",
+    "easyaudit",
+    "dbbackup",
+    "dbsettings",
+    "django_cron",
+    "bootstrap4",
+    "fa",
+    "django_any_js",
+    "django_yarnpkg",
+    "django_tables2",
+    "easy_thumbnails",
+    "image_cropping",
+    "maintenance_mode",
+    "menu_generator",
+    "phonenumber_field",
+    "debug_toolbar",
+    "django_select2",
+    "hattori",
+    "django_otp.plugins.otp_totp",
+    "django_otp.plugins.otp_static",
+    "django_otp",
+    "otp_yubikey",
+    "biscuit.core",
+    "impersonate",
+    "two_factor",
 ]
 
 INSTALLED_APPS += get_app_packages()
 
 STATICFILES_FINDERS = [
-    'django.contrib.staticfiles.finders.FileSystemFinder',
-    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-    'django_yarnpkg.finders.NodeModulesFinder',
-    'sass_processor.finders.CssFinder',
+    "django.contrib.staticfiles.finders.FileSystemFinder",
+    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
+    "django_yarnpkg.finders.NodeModulesFinder",
+    "sass_processor.finders.CssFinder",
 ]
 
 
 MIDDLEWARE = [
     #    'django.middleware.cache.UpdateCacheMiddleware',
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.locale.LocaleMiddleware',
-    'django_global_request.middleware.GlobalRequestMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'debug_toolbar.middleware.DebugToolbarMiddleware',
-    'django_otp.middleware.OTPMiddleware',
-    'impersonate.middleware.ImpersonateMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-    'easyaudit.middleware.easyaudit.EasyAuditMiddleware',
-    'maintenance_mode.middleware.MaintenanceModeMiddleware',
+    "django.middleware.security.SecurityMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "django.middleware.locale.LocaleMiddleware",
+    "django_global_request.middleware.GlobalRequestMiddleware",
+    "django.middleware.common.CommonMiddleware",
+    "django.middleware.csrf.CsrfViewMiddleware",
+    "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "debug_toolbar.middleware.DebugToolbarMiddleware",
+    "django_otp.middleware.OTPMiddleware",
+    "impersonate.middleware.ImpersonateMiddleware",
+    "django.contrib.messages.middleware.MessageMiddleware",
+    "django.middleware.clickjacking.XFrameOptionsMiddleware",
+    "easyaudit.middleware.easyaudit.EasyAuditMiddleware",
+    "maintenance_mode.middleware.MaintenanceModeMiddleware",
     #    'django.middleware.cache.FetchFromCacheMiddleware'
 ]
 
-ROOT_URLCONF = 'biscuit.core.urls'
+ROOT_URLCONF = "biscuit.core.urls"
 
 TEMPLATES = [
     {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
-                'maintenance_mode.context_processors.maintenance_mode',
-                'settings_context_processor.context_processors.settings',
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            "context_processors": [
+                "django.template.context_processors.debug",
+                "django.template.context_processors.request",
+                "django.contrib.auth.context_processors.auth",
+                "django.contrib.messages.context_processors.messages",
+                "maintenance_mode.context_processors.maintenance_mode",
+                "settings_context_processor.context_processors.settings",
             ],
         },
     },
 ]
 
 THUMBNAIL_PROCESSORS = (
-    'image_cropping.thumbnail_processors.crop_corners',
+    "image_cropping.thumbnail_processors.crop_corners",
 ) + thumbnail_settings.THUMBNAIL_PROCESSORS
 
 # Already included by base template / Bootstrap
 IMAGE_CROPPING_JQUERY_URL = None
 
-WSGI_APPLICATION = 'biscuit.core.wsgi.application'
+WSGI_APPLICATION = "biscuit.core.wsgi.application"
 
 
 # Database
 # https://docs.djangoproject.com/en/2.1/ref/settings/#databases
 
 DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.postgresql',
-        'NAME': _settings.get('database.name', 'biscuit'),
-        'USER': _settings.get('database.username', 'biscuit'),
-        'PASSWORD': _settings.get('database.password', None),
-        'HOST': _settings.get('database.host', '127.0.0.1'),
-        'PORT': _settings.get('database.port', '5432'),
-        'ATOMIC_REQUESTS': True,
+    "default": {
+        "ENGINE": "django.db.backends.postgresql",
+        "NAME": _settings.get("database.name", "biscuit"),
+        "USER": _settings.get("database.username", "biscuit"),
+        "PASSWORD": _settings.get("database.password", None),
+        "HOST": _settings.get("database.host", "127.0.0.1"),
+        "PORT": _settings.get("database.port", "5432"),
+        "ATOMIC_REQUESTS": True,
     }
 }
 
-if _settings.get('caching.memcached.enabled', True):
+if _settings.get("caching.memcached.enabled", True):
     CACHES = {
-        'default': {
-            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
-            'LOCATION': _settings.get('caching.memcached.address', '127.0.0.1:11211'),
+        "default": {
+            "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
+            "LOCATION": _settings.get("caching.memcached.address", "127.0.0.1:11211"),
         }
     }
 
@@ -164,57 +164,57 @@ if _settings.get('caching.memcached.enabled', True):
 # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
 
 AUTH_PASSWORD_VALIDATORS = [
-    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},
-    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},
-    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},
-    {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},
+    {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",},
+    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
+    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
+    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
 ]
 
 # Authentication backends are dynamically populated
 AUTHENTICATION_BACKENDS = []
 
-if _settings.get('ldap.uri', None):
+if _settings.get("ldap.uri", None):
     # LDAP dependencies are not necessarily installed, so import them here
     import ldap  # noqa
     from django_auth_ldap.config import LDAPSearch, GroupOfNamesType  # noqa
 
     # Enable Django's integration to LDAP
-    AUTHENTICATION_BACKENDS.append('django_auth_ldap.backend.LDAPBackend')
+    AUTHENTICATION_BACKENDS.append("django_auth_ldap.backend.LDAPBackend")
 
-    AUTH_LDAP_SERVER_URI = _settings.get('ldap.uri')
+    AUTH_LDAP_SERVER_URI = _settings.get("ldap.uri")
 
     # Optional: non-anonymous bind
-    if _settings.get('ldap.bind.dn', None):
-        AUTH_LDAP_BIND_DN = _settings.get('ldap.bind.dn')
-        AUTH_LDAP_BIND_PASSWORD = _settings.get('ldap.bind.password')
+    if _settings.get("ldap.bind.dn", None):
+        AUTH_LDAP_BIND_DN = _settings.get("ldap.bind.dn")
+        AUTH_LDAP_BIND_PASSWORD = _settings.get("ldap.bind.password")
 
     # Search attributes to find users by username
     AUTH_LDAP_USER_SEARCH = LDAPSearch(
-        _settings.get('ldap.users.base'),
+        _settings.get("ldap.users.base"),
         ldap.SCOPE_SUBTREE,
-        _settings.get('ldap.users.filter', '(uid=%(user)s)'),
+        _settings.get("ldap.users.filter", "(uid=%(user)s)"),
     )
 
     # Mapping of LDAP attributes to Django model fields
     AUTH_LDAP_USER_ATTR_MAP = {
-        'first_name': _settings.get('ldap.map.first_name', 'givenName'),
-        'last_name': _settings.get('ldap.map.first_name', 'sn'),
-        'email': _settings.get('ldap.map.email', 'mail'),
+        "first_name": _settings.get("ldap.map.first_name", "givenName"),
+        "last_name": _settings.get("ldap.map.first_name", "sn"),
+        "email": _settings.get("ldap.map.email", "mail"),
     }
 
 # Add ModelBckend last so all other backends get a chance
 # to verify passwords first
-AUTHENTICATION_BACKENDS.append('django.contrib.auth.backends.ModelBackend')
+AUTHENTICATION_BACKENDS.append("django.contrib.auth.backends.ModelBackend")
 
 # Internationalization
 # https://docs.djangoproject.com/en/2.1/topics/i18n/
 
 LANGUAGES = [
-    ('de', _('German')),
-    ('en', _('English')),
+    ("de", _("German")),
+    ("en", _("English")),
 ]
-LANGUAGE_CODE = _settings.get('l10n.lang', 'en')
-TIME_ZONE = _settings.get('l10n.tz', 'UTC')
+LANGUAGE_CODE = _settings.get("l10n.lang", "en")
+TIME_ZONE = _settings.get("l10n.tz", "UTC")
 USE_I18N = True
 USE_L10N = True
 USE_TZ = True
@@ -223,108 +223,108 @@ USE_TZ = True
 # https://docs.djangoproject.com/en/2.1/howto/static-files/
 
 
-STATIC_URL = _settings.get('static.url', '/static/')
-MEDIA_URL = _settings.get('media.url', '/media/')
+STATIC_URL = _settings.get("static.url", "/static/")
+MEDIA_URL = _settings.get("media.url", "/media/")
 
-LOGIN_REDIRECT_URL = 'index'
-LOGOUT_REDIRECT_URL = 'index'
+LOGIN_REDIRECT_URL = "index"
+LOGOUT_REDIRECT_URL = "index"
 
-STATIC_ROOT = _settings.get('static.root', os.path.join(BASE_DIR, 'static'))
-MEDIA_ROOT = _settings.get('media.root', os.path.join(BASE_DIR, 'media'))
-NODE_MODULES_ROOT = _settings.get('node_modules.root', os.path.join(BASE_DIR, 'node_modules'))
+STATIC_ROOT = _settings.get("static.root", os.path.join(BASE_DIR, "static"))
+MEDIA_ROOT = _settings.get("media.root", os.path.join(BASE_DIR, "media"))
+NODE_MODULES_ROOT = _settings.get("node_modules.root", os.path.join(BASE_DIR, "node_modules"))
 
-YARN_INSTALLED_APPS = ['bootstrap', 'font-awesome', 'jquery', 'popper.js', 'datatables', 'select2']
+YARN_INSTALLED_APPS = ["bootstrap", "font-awesome", "jquery", "popper.js", "datatables", "select2"]
 
-JS_URL = _settings.get('js_assets.url', STATIC_URL)
-JS_ROOT = _settings.get('js_assets.root', NODE_MODULES_ROOT + '/node_modules')
+JS_URL = _settings.get("js_assets.url", STATIC_URL)
+JS_ROOT = _settings.get("js_assets.root", NODE_MODULES_ROOT + "/node_modules")
 
-FONT_AWESOME = {'url': JS_URL + '/font-awesome/css/font-awesome.min.css'}
+FONT_AWESOME = {"url": JS_URL + "/font-awesome/css/font-awesome.min.css"}
 
 BOOTSTRAP4 = {
-    'css_url': JS_URL + '/bootstrap/dist//css/bootstrap.min.css',
-    'javascript_url': JS_URL + '/bootstrap/dist/js/bootstrap.min.js',
-    'jquery_url': JS_URL + '/jquery/dist/jquery.min.js',
-    'popper_url': JS_URL + '/popper.js/dist/umd/popper.min.js',
-    'include_jquery': True,
-    'include_popper': True,
-    'javascript_in_head': True,
+    "css_url": JS_URL + "/bootstrap/dist//css/bootstrap.min.css",
+    "javascript_url": JS_URL + "/bootstrap/dist/js/bootstrap.min.js",
+    "jquery_url": JS_URL + "/jquery/dist/jquery.min.js",
+    "popper_url": JS_URL + "/popper.js/dist/umd/popper.min.js",
+    "include_jquery": True,
+    "include_popper": True,
+    "javascript_in_head": True,
 }
 
-SELECT2_CSS = JS_URL + '/select2/dist/css/select2.min.css'
-SELECT2_JS = JS_URL + '/select2/dist/js/select2.min.js'
-SELECT2_I18N_PATH = JS_URL + '/select2/dist/js/i18n'
+SELECT2_CSS = JS_URL + "/select2/dist/css/select2.min.css"
+SELECT2_JS = JS_URL + "/select2/dist/js/select2.min.js"
+SELECT2_I18N_PATH = JS_URL + "/select2/dist/js/i18n"
 
 ANY_JS = {
-    'DataTables': {'js_url': JS_URL + '/datatables/media/js/jquery.dataTables.min.js'},
-    'DataTables-Bootstrap4': {
-        'css_url': JS_URL + '/datatables/media/css/dataTables.bootstrap4.min.css',
-        'js_url': JS_URL + '/datatables/media/js/dataTables.bootstrap4.min.js',
+    "DataTables": {"js_url": JS_URL + "/datatables/media/js/jquery.dataTables.min.js"},
+    "DataTables-Bootstrap4": {
+        "css_url": JS_URL + "/datatables/media/css/dataTables.bootstrap4.min.css",
+        "js_url": JS_URL + "/datatables/media/js/dataTables.bootstrap4.min.js",
     },
 }
 
 SASS_PROCESSOR_AUTO_INCLUDE = False
 SASS_PROCESSOR_CUSTOM_FUNCTIONS = {
-    'get-colour': 'biscuit.core.util.sass_helpers.get_colour',
-    'get-theme-setting': 'biscuit.core.util.sass_helpers.get_theme_setting',
+    "get-colour": "biscuit.core.util.sass_helpers.get_colour",
+    "get-theme-setting": "biscuit.core.util.sass_helpers.get_theme_setting",
 }
-SASS_PROCESSOR_INCLUDE_DIRS = [_settings.get('bootstrap.sass_path', JS_ROOT + '/bootstrap/scss/')]
-
-ADMINS = _settings.get('contact.admins', [])
-SERVER_EMAIL = _settings.get('contact.from', 'root@localhost')
-DEFAULT_FROM_EMAIL = _settings.get('contact.from', 'root@localhost')
-MANAGERS = _settings.get('contact.admins', [])
-
-if _settings.get('mail.server.host', None):
-    EMAIL_HOST = _settings.get('mail.server.host')
-    EMAIL_USE_TLS = _settings.get('mail.server.tls', False)
-    EMAIL_USE_SSL = _settings.get('mail.server.ssl', False)
-    if _settings.get('mail.server.port', None):
-        EMAIL_PORT = _settings.get('mail.server.port')
-    if _settings.get('mail.server.user', None):
-        EMAIL_HOST_USER = _settings.get('mail.server.user')
-        EMAIL_HOST_PASSWORD = _settings.get('mail.server.password')
-
-TEMPLATE_VISIBLE_SETTINGS = ['ADMINS', 'DEBUG']
-
-MAINTENANCE_MODE = _settings.get('maintenance.enabled', None)
+SASS_PROCESSOR_INCLUDE_DIRS = [_settings.get("bootstrap.sass_path", JS_ROOT + "/bootstrap/scss/")]
+
+ADMINS = _settings.get("contact.admins", [])
+SERVER_EMAIL = _settings.get("contact.from", "root@localhost")
+DEFAULT_FROM_EMAIL = _settings.get("contact.from", "root@localhost")
+MANAGERS = _settings.get("contact.admins", [])
+
+if _settings.get("mail.server.host", None):
+    EMAIL_HOST = _settings.get("mail.server.host")
+    EMAIL_USE_TLS = _settings.get("mail.server.tls", False)
+    EMAIL_USE_SSL = _settings.get("mail.server.ssl", False)
+    if _settings.get("mail.server.port", None):
+        EMAIL_PORT = _settings.get("mail.server.port")
+    if _settings.get("mail.server.user", None):
+        EMAIL_HOST_USER = _settings.get("mail.server.user")
+        EMAIL_HOST_PASSWORD = _settings.get("mail.server.password")
+
+TEMPLATE_VISIBLE_SETTINGS = ["ADMINS", "DEBUG"]
+
+MAINTENANCE_MODE = _settings.get("maintenance.enabled", None)
 MAINTENANCE_MODE_IGNORE_IP_ADDRESSES = _settings.get(
-    'maintenance.ignore_ips', _settings.get('maintenance.internal_ips', [])
+    "maintenance.ignore_ips", _settings.get("maintenance.internal_ips", [])
 )
-MAINTENANCE_MODE_GET_CLIENT_IP_ADDRESS = 'ipware.ip.get_ip'
+MAINTENANCE_MODE_GET_CLIENT_IP_ADDRESS = "ipware.ip.get_ip"
 MAINTENANCE_MODE_IGNORE_SUPERUSER = True
 MAINTENANCE_MODE_STATE_FILE_PATH = _settings.get(
-    'maintenance.statefile', 'maintenance_mode_state.txt'
+    "maintenance.statefile", "maintenance_mode_state.txt"
 )
 
-IMPERSONATE = {'USE_HTTP_REFERER': True, 'REQUIRE_SUPERUSER': True, 'ALLOW_SUPERUSER': True}
+IMPERSONATE = {"USE_HTTP_REFERER": True, "REQUIRE_SUPERUSER": True, "ALLOW_SUPERUSER": True}
 
 DJANGO_TABLES2_TEMPLATE = "django_tables2/bootstrap4.html"
 
-DBBACKUP_STORAGE = _settings.get('backup.storage', 'django.core.files.storage.FileSystemStorage')
-DBBACKUP_STORAGE_OPTIONS = {'location': _settings.get('backup.location', '/var/backups/biscuit')}
-DBBACKUP_CLEANUP_KEEP = _settings.get('backup.keep.database', 10)
-DBBACKUP_CLEANUP_KEEP_MEDIA = _settings.get('backup.keep.media', 10)
-DBBACKUP_CRON_TIMES = _settings.get('backup.times', None) or ['03:57']
+DBBACKUP_STORAGE = _settings.get("backup.storage", "django.core.files.storage.FileSystemStorage")
+DBBACKUP_STORAGE_OPTIONS = {"location": _settings.get("backup.location", "/var/backups/biscuit")}
+DBBACKUP_CLEANUP_KEEP = _settings.get("backup.keep.database", 10)
+DBBACKUP_CLEANUP_KEEP_MEDIA = _settings.get("backup.keep.media", 10)
+DBBACKUP_CRON_TIMES = _settings.get("backup.times", None) or ["03:57"]
 
-CRON_CLASSES = ['biscuit.core.cronjobs.Backup']
+CRON_CLASSES = ["biscuit.core.cronjobs.Backup"]
 
-ANONYMIZE_ENABLED = _settings.get('maintenance.anonymisable', True)
+ANONYMIZE_ENABLED = _settings.get("maintenance.anonymisable", True)
 
-LOGIN_URL = 'two_factor:login'
+LOGIN_URL = "two_factor:login"
 
-if _settings.get('2fa.call.enabled', False):
-    TWO_FACTOR_CALL_GATEWAY = 'two_factor.gateways.twilio.gateway.Twilio'
+if _settings.get("2fa.call.enabled", False):
+    TWO_FACTOR_CALL_GATEWAY = "two_factor.gateways.twilio.gateway.Twilio"
 
-if _settings.get('2fa.sms.enabled', False):
-    TWO_FACTOR_SMS_GATEWAY = 'two_factor.gateways.twilio.gateway.Twilio'
+if _settings.get("2fa.sms.enabled", False):
+    TWO_FACTOR_SMS_GATEWAY = "two_factor.gateways.twilio.gateway.Twilio"
 
-if _settings.get('2fa.twilio.sid', None):
+if _settings.get("2fa.twilio.sid", None):
     MIDDLEWARE.insert(
-        MIDDLEWARE.index('django_otp.middleware.OTPMiddleware') + 1,
-        'two_factor.middleware.threadlocals.ThreadLocals',
+        MIDDLEWARE.index("django_otp.middleware.OTPMiddleware") + 1,
+        "two_factor.middleware.threadlocals.ThreadLocals",
     )
-    TWILIO_SID = _settings.get('2fa.twilio.sid')
-    TWILIO_TOKEN = _settings.get('2fa.twilio.token')
-    TWILIO_CALLER_ID = _settings.get('2fa.twilio.callerid')
+    TWILIO_SID = _settings.get("2fa.twilio.sid")
+    TWILIO_TOKEN = _settings.get("2fa.twilio.token")
+    TWILIO_CALLER_ID = _settings.get("2fa.twilio.callerid")
 
 _settings.populate_obj(sys.modules[__name__])
diff --git a/biscuit/core/signals.py b/biscuit/core/signals.py
index e531c5b9ed0158c3986144ab68e6c0eaeea9eda9..2a2e34198624d4cd7c8e1f3c08869d787e1b8483 100644
--- a/biscuit/core/signals.py
+++ b/biscuit/core/signals.py
@@ -5,7 +5,7 @@ from django.conf import settings
 
 
 def clean_scss(*args, **kwargs) -> None:
-    for source_map in glob(os.path.join(settings.STATIC_ROOT, '*.css.map')):
+    for source_map in glob(os.path.join(settings.STATIC_ROOT, "*.css.map")):
         try:
             os.unlink(source_map)
         except OSError:
diff --git a/biscuit/core/tables.py b/biscuit/core/tables.py
index 39edd10b77bea1d75d1ad532ba387383bc093513..b8190272916e32cc67007d31409963d42bd02b8d 100644
--- a/biscuit/core/tables.py
+++ b/biscuit/core/tables.py
@@ -4,15 +4,15 @@ from django_tables2.utils import A
 
 class PersonsTable(tables.Table):
     class Meta:
-        attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'}
+        attrs = {"class": "table table-striped table-bordered table-hover table-responsive-xl"}
 
-    first_name = tables.LinkColumn('person_by_id', args=[A('id')])
-    last_name = tables.LinkColumn('person_by_id', args=[A('id')])
+    first_name = tables.LinkColumn("person_by_id", args=[A("id")])
+    last_name = tables.LinkColumn("person_by_id", args=[A("id")])
 
 
 class GroupsTable(tables.Table):
     class Meta:
-        attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'}
+        attrs = {"class": "table table-striped table-bordered table-hover table-responsive-xl"}
 
-    name = tables.LinkColumn('group_by_id', args=[A('id')])
-    short_name = tables.LinkColumn('group_by_id', args=[A('id')])
+    name = tables.LinkColumn("group_by_id", args=[A("id")])
+    short_name = tables.LinkColumn("group_by_id", args=[A("id")])
diff --git a/biscuit/core/templatetags/data_helpers.py b/biscuit/core/templatetags/data_helpers.py
index 66b41efd37e7ddbae179dd2d6dfef619f0ff3c98..0b195d136d86587f892635d6d0e41be1aebada68 100644
--- a/biscuit/core/templatetags/data_helpers.py
+++ b/biscuit/core/templatetags/data_helpers.py
@@ -11,7 +11,7 @@ def get_dict(value: Any, arg: Any) -> Any:
 
     if hasattr(value, str(arg)):
         return getattr(value, arg)
-    elif hasattr(value, 'keys') and arg in value.keys():
+    elif hasattr(value, "keys") and arg in value.keys():
         return value[arg]
     elif str(arg).isnumeric() and len(value) > int(arg):
         return value[int(arg)]
diff --git a/biscuit/core/tests/browser/test_selenium.py b/biscuit/core/tests/browser/test_selenium.py
index 21705ba508ee81825c7cbfecadbd6c09676fb9ab..795e23799320d1d7c2897bf6539f2e82af7427cb 100644
--- a/biscuit/core/tests/browser/test_selenium.py
+++ b/biscuit/core/tests/browser/test_selenium.py
@@ -6,11 +6,11 @@ from django.conf import settings
 from django.test.selenium import SeleniumTestCase, SeleniumTestCaseBase
 from django.urls import reverse
 
-SeleniumTestCaseBase.external_host = os.environ.get('TEST_HOST', '') or None
+SeleniumTestCaseBase.external_host = os.environ.get("TEST_HOST", "") or None
 SeleniumTestCaseBase.browsers = list(
-    filter(bool, os.environ.get('TEST_SELENIUM_BROWSERS', '').split(','))
+    filter(bool, os.environ.get("TEST_SELENIUM_BROWSERS", "").split(","))
 )
-SeleniumTestCaseBase.selenium_hub = os.environ.get('TEST_SELENIUM_HUB', '') or None
+SeleniumTestCaseBase.selenium_hub = os.environ.get("TEST_SELENIUM_HUB", "") or None
 
 
 class SeleniumTests(SeleniumTestCase):
@@ -18,7 +18,7 @@ class SeleniumTests(SeleniumTestCase):
 
     @classmethod
     def _screenshot(cls, filename):
-        screenshot_path = os.environ.get('TEST_SCREENSHOT_PATH', None)
+        screenshot_path = os.environ.get("TEST_SCREENSHOT_PATH", None)
         if screenshot_path:
             os.makedirs(os.path.join(screenshot_path, cls.browser), exist_ok=True)
             return cls.selenium.save_screenshot(
@@ -29,18 +29,18 @@ class SeleniumTests(SeleniumTestCase):
 
     @pytest.mark.django_db
     def test_index(self):
-        self.selenium.get(self.live_server_url + '/')
-        assert 'BiscuIT' in self.selenium.title
-        self._screenshot('index.png')
+        self.selenium.get(self.live_server_url + "/")
+        assert "BiscuIT" in self.selenium.title
+        self._screenshot("index.png")
 
     @pytest.mark.django_db
     def test_login_default_superuser(self):
-        username = 'admin'
-        password = 'admin'
+        username = "admin"
+        password = "admin"
 
         # Navigate to configured login page
         self.selenium.get(self.live_server_url + reverse(settings.LOGIN_URL))
-        self._screenshot('login_default_superuser_blank.png')
+        self._screenshot("login_default_superuser_blank.png")
 
         # Find login form input fields and enter defined credentials
         self.selenium.find_element_by_xpath(
@@ -49,12 +49,12 @@ class SeleniumTests(SeleniumTestCase):
         self.selenium.find_element_by_xpath(
             '//label[contains(text(), "Password")]/../input'
         ).send_keys(password)
-        self._screenshot('login_default_superuser_filled.png')
+        self._screenshot("login_default_superuser_filled.png")
 
         # Submit form by clicking django-two-factor-auth's Next button
         self.selenium.find_element_by_xpath('//button[contains(text(), "Next")]').click()
-        self._screenshot('login_default_superuser_submitted.png')
+        self._screenshot("login_default_superuser_submitted.png")
 
         # Should redirect away from login page and not put up an alert about wrong credentials
-        assert 'Please enter a correct username and password.' not in self.selenium.page_source
+        assert "Please enter a correct username and password." not in self.selenium.page_source
         assert reverse(settings.LOGIN_URL) not in self.selenium.current_url
diff --git a/biscuit/core/tests/models/test_person.py b/biscuit/core/tests/models/test_person.py
index 328f459b3b5859ac422a08cb61acbe1ea31715c5..740031df0c419221d0299c7b3079ac4c2d490d1c 100644
--- a/biscuit/core/tests/models/test_person.py
+++ b/biscuit/core/tests/models/test_person.py
@@ -5,6 +5,6 @@ from biscuit.core.models import Person
 
 @pytest.mark.django_db
 def test_full_name():
-    _person = Person.objects.create(first_name='Jane', last_name='Doe')
+    _person = Person.objects.create(first_name="Jane", last_name="Doe")
 
-    assert _person.full_name == 'Doe, Jane'
+    assert _person.full_name == "Doe, Jane"
diff --git a/biscuit/core/tests/templatetags/test_data_helpers.py b/biscuit/core/tests/templatetags/test_data_helpers.py
index 22281a18462088f3bceef6f94a84f8f60200612f..5f8e975ffdffb5b522ee94927add0a38d742045f 100644
--- a/biscuit/core/tests/templatetags/test_data_helpers.py
+++ b/biscuit/core/tests/templatetags/test_data_helpers.py
@@ -5,13 +5,13 @@ def test_get_dict_object():
     class _Foo(object):
         bar = 12
 
-    assert _Foo.bar == get_dict(_Foo, 'bar')
+    assert _Foo.bar == get_dict(_Foo, "bar")
 
 
 def test_get_dict_dict():
-    _foo = {'bar': 12}
+    _foo = {"bar": 12}
 
-    assert _foo['bar'] == get_dict(_foo, 'bar')
+    assert _foo["bar"] == get_dict(_foo, "bar")
 
 
 def test_get_dict_list():
@@ -23,4 +23,4 @@ def test_get_dict_list():
 def test_get_dict_invalid():
     _foo = 12
 
-    assert get_dict(_foo, 'bar') is None
+    assert get_dict(_foo, "bar") is None
diff --git a/biscuit/core/tests/views/test_account.py b/biscuit/core/tests/views/test_account.py
index 6a5971720ab70e680e8dcc5688e27f6483705fbc..16016665f4a39daa249ca7c211f5bd01aa07a3c0 100644
--- a/biscuit/core/tests/views/test_account.py
+++ b/biscuit/core/tests/views/test_account.py
@@ -6,52 +6,52 @@ from django.urls import reverse
 
 @pytest.mark.django_db
 def test_index_not_logged_in(client):
-    response = client.get('/')
+    response = client.get("/")
 
     assert response.status_code == 200
-    assert reverse(settings.LOGIN_URL) in response.content.decode('utf-8')
+    assert reverse(settings.LOGIN_URL) in response.content.decode("utf-8")
 
 
 @pytest.mark.django_db
 def test_login(client, django_user_model):
-    username = 'foo'
-    password = 'bar'
+    username = "foo"
+    password = "bar"
 
     django_user_model.objects.create_user(username=username, password=password)
     client.login(username=username, password=password)
 
-    response = client.get('/')
+    response = client.get("/")
 
     assert response.status_code == 200
-    assert reverse(settings.LOGIN_URL) not in response.content.decode('utf-8')
+    assert reverse(settings.LOGIN_URL) not in response.content.decode("utf-8")
 
 
 @pytest.mark.django_db
 def test_index_not_linked_to_person(client, django_user_model):
-    username = 'foo'
-    password = 'bar'
+    username = "foo"
+    password = "bar"
 
     django_user_model.objects.create_user(username=username, password=password)
     client.login(username=username, password=password)
 
-    response = client.get('/')
+    response = client.get("/")
 
     assert response.status_code == 200
-    assert 'You are not linked to a person' in response.content.decode('utf-8')
+    assert "You are not linked to a person" in response.content.decode("utf-8")
 
 
 @pytest.mark.django_db
 def test_logout(client, django_user_model):
-    username = 'foo'
-    password = 'bar'
+    username = "foo"
+    password = "bar"
 
     django_user_model.objects.create_user(username=username, password=password)
     client.login(username=username, password=password)
 
-    response = client.get('/')
+    response = client.get("/")
     assert response.status_code == 200
 
-    response = client.get(reverse('logout'), follow=True)
+    response = client.get(reverse("logout"), follow=True)
 
     assert response.status_code == 200
-    assert reverse(settings.LOGIN_URL) in response.content.decode('utf-8')
+    assert reverse(settings.LOGIN_URL) in response.content.decode("utf-8")
diff --git a/biscuit/core/urls.py b/biscuit/core/urls.py
index 3b172dc5e7558df97b05cd02df1b1da35bc6d9d0..470f5471d988b0facd52882404ae394e79bba134 100644
--- a/biscuit/core/urls.py
+++ b/biscuit/core/urls.py
@@ -11,30 +11,30 @@ from two_factor.urls import urlpatterns as tf_urls
 from . import views
 
 urlpatterns = [
-    path('admin/', admin.site.urls),
-    path('data_management/', views.data_management, name='data_management'),
-    path('status/', views.system_status, name='system_status'),
-    path('school_management', views.school_management, name='school_management'),
-    path('school/information/edit', views.edit_school, name='edit_school_information'),
-    path('school/term/edit', views.edit_schoolterm, name='edit_school_term'),
-    path('', include(tf_urls)),
-    path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'),
-    path('persons', views.persons, name='persons'),
-    path('persons/accounts', views.persons_accounts, name='persons_accounts'),
-    path('person', views.person, name='person'),
-    path('person/<int:id_>', views.person, {'template': 'full'}, name='person_by_id'),
-    path('person/<int:id_>/card', views.person, {'template': 'card'}, name='person_by_id_card'),
-    path('person/<int:id_>/edit', views.edit_person, name='edit_person_by_id'),
-    path('groups', views.groups, name='groups'),
-    path('group/create', views.edit_group, name='create_group'),
-    path('group/<int:id_>', views.group, {'template': 'full'}, name='group_by_id'),
-    path('group/<int:id_>/edit', views.edit_group, name='edit_group_by_id'),
-    path('', views.index, name='index'),
-    path('maintenance-mode/', include('maintenance_mode.urls')),
-    path('impersonate/', include('impersonate.urls')),
-    path('__i18n__/', include('django.conf.urls.i18n')),
-    path('select2/', include('django_select2.urls')),
-    path('settings/', include('dbsettings.urls')),
+    path("admin/", admin.site.urls),
+    path("data_management/", views.data_management, name="data_management"),
+    path("status/", views.system_status, name="system_status"),
+    path("school_management", views.school_management, name="school_management"),
+    path("school/information/edit", views.edit_school, name="edit_school_information"),
+    path("school/term/edit", views.edit_schoolterm, name="edit_school_term"),
+    path("", include(tf_urls)),
+    path("accounts/logout/", auth_views.LogoutView.as_view(), name="logout"),
+    path("persons", views.persons, name="persons"),
+    path("persons/accounts", views.persons_accounts, name="persons_accounts"),
+    path("person", views.person, name="person"),
+    path("person/<int:id_>", views.person, {"template": "full"}, name="person_by_id"),
+    path("person/<int:id_>/card", views.person, {"template": "card"}, name="person_by_id_card"),
+    path("person/<int:id_>/edit", views.edit_person, name="edit_person_by_id"),
+    path("groups", views.groups, name="groups"),
+    path("group/create", views.edit_group, name="create_group"),
+    path("group/<int:id_>", views.group, {"template": "full"}, name="group_by_id"),
+    path("group/<int:id_>/edit", views.edit_group, name="edit_group_by_id"),
+    path("", views.index, name="index"),
+    path("maintenance-mode/", include("maintenance_mode.urls")),
+    path("impersonate/", include("impersonate.urls")),
+    path("__i18n__/", include("django.conf.urls.i18n")),
+    path("select2/", include("django_select2.urls")),
+    path("settings/", include("dbsettings.urls")),
 ]
 
 # Serve static files from STATIC_ROOT to make it work with runserver
@@ -42,18 +42,18 @@ urlpatterns = [
 urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
 
 # Add URLs for optional features
-if hasattr(settings, 'TWILIO_ACCOUNT_SID'):
+if hasattr(settings, "TWILIO_ACCOUNT_SID"):
     from two_factor.gateways.twilio.urls import urlpatterns as tf_twilio_urls  # noqa
 
-    urlpatterns += [path('', include(tf_twilio_urls))]
+    urlpatterns += [path("", include(tf_twilio_urls))]
 
 # Serve javascript-common if in development
 if settings.DEBUG:
-    urlpatterns.append(path('__debug__/', include(debug_toolbar.urls)))
+    urlpatterns.append(path("__debug__/", include(debug_toolbar.urls)))
 
 # Automatically mount URLs from all installed BiscuIT apps
 for app_config in apps.app_configs.values():
-    if not app_config.name.startswith('biscuit.apps.'):
+    if not app_config.name.startswith("biscuit.apps."):
         continue
 
-    urlpatterns.append(path('app/%s/' % app_config.label, include('%s.urls' % app_config.name)))
+    urlpatterns.append(path("app/%s/" % app_config.label, include("%s.urls" % app_config.name)))
diff --git a/biscuit/core/util/apps.py b/biscuit/core/util/apps.py
index 9b732d651caae3412e002717e57c518c515bbdae..f98649cdc261b21443cfc1696af2453c119b6f79 100644
--- a/biscuit/core/util/apps.py
+++ b/biscuit/core/util/apps.py
@@ -12,7 +12,7 @@ class AppConfig(django.apps.AppConfig):
         # Run model extension code
         try:
             import_module(
-                '.'.join(self.__class__.__module__.split('.')[:-1] + ['model_extensions'])
+                ".".join(self.__class__.__module__.split(".")[:-1] + ["model_extensions"])
             )
         except ImportError:
             # ImportErrors are non-fatal because model extensions are optional.
diff --git a/biscuit/core/util/core_helpers.py b/biscuit/core/util/core_helpers.py
index 4089026c884b03abe83a468e0949853581bcdf39..d66eb3a53bc9bcf2565664deaccc1436888428bb 100644
--- a/biscuit/core/util/core_helpers.py
+++ b/biscuit/core/util/core_helpers.py
@@ -14,7 +14,7 @@ def dt_show_toolbar(request: HttpRequest) -> bool:
 
     if show_toolbar(request):
         return True
-    elif hasattr(request, 'user') and request.user.is_superuser:
+    elif hasattr(request, "user") and request.user.is_superuser:
         return True
 
     return False
@@ -31,28 +31,28 @@ def get_app_packages() -> Sequence[str]:
 
     pkgs = []
     for pkg in pkgutil.iter_modules(biscuit.apps.__path__):
-        mod = import_module('biscuit.apps.%s' % pkg[1])
+        mod = import_module("biscuit.apps.%s" % pkg[1])
 
         # Add additional apps defined in module's INSTALLED_APPS constant
-        additional_apps = getattr(mod, 'INSTALLED_APPS', [])
+        additional_apps = getattr(mod, "INSTALLED_APPS", [])
         for app in additional_apps:
             if app not in pkgs:
                 pkgs.append(app)
 
-        pkgs.append('biscuit.apps.%s' % pkg[1])
+        pkgs.append("biscuit.apps.%s" % pkg[1])
 
     return pkgs
 
 
 def is_impersonate(request: HttpRequest) -> bool:
-    if hasattr(request, 'user'):
-        return getattr(request.user, 'is_impersonate', False)
+    if hasattr(request, "user"):
+        return getattr(request.user, "is_impersonate", False)
     else:
         return False
 
 
 def has_person(request: HttpRequest) -> bool:
-    if hasattr(request, 'user'):
-        return getattr(request.user, 'person', None) is not None
+    if hasattr(request, "user"):
+        return getattr(request.user, "person", None) is not None
     else:
         return False
diff --git a/biscuit/core/util/sass_helpers.py b/biscuit/core/util/sass_helpers.py
index c609c0ed9941c1485edfb1d7e8111c1a06b414eb..9dbb56bf2652dbd385b1faa2e21c5575642e459a 100644
--- a/biscuit/core/util/sass_helpers.py
+++ b/biscuit/core/util/sass_helpers.py
@@ -12,4 +12,4 @@ def get_colour(html_colour: str) -> SassColor:
 
 
 def get_theme_setting(setting: str) -> str:
-    return getattr(theme_settings, setting, '')
+    return getattr(theme_settings, setting, "")
diff --git a/biscuit/core/views.py b/biscuit/core/views.py
index d3eb0e7752f964afc1d5ae630e65835dbe6f65ca..999f911d3eabd0171e71af83372128c0236135b3 100644
--- a/biscuit/core/views.py
+++ b/biscuit/core/views.py
@@ -23,7 +23,7 @@ from .util import messages
 
 def index(request: HttpRequest) -> HttpResponse:
     context = {}
-    return render(request, 'core/index.html', context)
+    return render(request, "core/index.html", context)
 
 
 @login_required
@@ -36,9 +36,9 @@ def persons(request: HttpRequest) -> HttpResponse:
     # Build table
     persons_table = PersonsTable(persons)
     RequestConfig(request).configure(persons_table)
-    context['persons_table'] = persons_table
+    context["persons_table"] = persons_table
 
-    return render(request, 'core/persons.html', context)
+    return render(request, "core/persons.html", context)
 
 
 @login_required
@@ -52,7 +52,7 @@ def person(request: HttpRequest, id_: int, template: str) -> HttpResponse:
         # Turn not-found object into a 404 error
         raise Http404 from e
 
-    context['person'] = person
+    context["person"] = person
 
     # Get groups where person is member of
     groups = Group.objects.filter(members=id_)
@@ -60,9 +60,9 @@ def person(request: HttpRequest, id_: int, template: str) -> HttpResponse:
     # Build table
     groups_table = GroupsTable(groups)
     RequestConfig(request).configure(groups_table)
-    context['groups_table'] = groups_table
+    context["groups_table"] = groups_table
 
-    return render(request, 'core/person_%s.html' % template, context)
+    return render(request, "core/person_%s.html" % template, context)
 
 
 @login_required
@@ -76,7 +76,7 @@ def group(request: HttpRequest, id_: int, template: str) -> HttpResponse:
         # Turn not-found object into a 404 error
         raise Http404 from e
 
-    context['group'] = group
+    context["group"] = group
 
     # Get group
     group = Group.objects.get(pk=id_)
@@ -87,7 +87,7 @@ def group(request: HttpRequest, id_: int, template: str) -> HttpResponse:
     # Build table
     members_table = PersonsTable(members)
     RequestConfig(request).configure(members_table)
-    context['members_table'] = members_table
+    context["members_table"] = members_table
 
     # Get owners
     owners = group.owners.filter(is_active=True)
@@ -95,9 +95,9 @@ def group(request: HttpRequest, id_: int, template: str) -> HttpResponse:
     # Build table
     owners_table = PersonsTable(owners)
     RequestConfig(request).configure(owners_table)
-    context['owners_table'] = owners_table
+    context["owners_table"] = owners_table
 
-    return render(request, 'core/group_%s.html' % template, context)
+    return render(request, "core/group_%s.html" % template, context)
 
 
 @login_required
@@ -110,9 +110,9 @@ def groups(request: HttpRequest) -> HttpResponse:
     # Build table
     groups_table = GroupsTable(groups)
     RequestConfig(request).configure(groups_table)
-    context['groups_table'] = groups_table
+    context["groups_table"] = groups_table
 
-    return render(request, 'core/groups.html', context)
+    return render(request, "core/groups.html", context)
 
 
 @admin_required
@@ -122,13 +122,13 @@ def persons_accounts(request: HttpRequest) -> HttpResponse:
     persons_qs = Person.objects.all()
     persons_accounts_formset = PersonsAccountsFormSet(request.POST or None, queryset=persons_qs)
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if persons_accounts_formset.is_valid():
             persons_accounts_formset.save()
 
-    context['persons_accounts_formset'] = persons_accounts_formset
+    context["persons_accounts_formset"] = persons_accounts_formset
 
-    return render(request, 'core/persons_accounts.html', context)
+    return render(request, "core/persons_accounts.html", context)
 
 
 @admin_required
@@ -139,18 +139,18 @@ def edit_person(request: HttpRequest, id_: int) -> HttpResponse:
 
     edit_person_form = EditPersonForm(request.POST or None, request.FILES or None, instance=person)
 
-    context['person'] = person
+    context["person"] = person
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if edit_person_form.is_valid():
             edit_person_form.save(commit=True)
 
-            messages.success(request, _('The person has been saved.'))
-            return redirect('edit_person_by_id', id_=person.id)
+            messages.success(request, _("The person has been saved."))
+            return redirect("edit_person_by_id", id_=person.id)
 
-    context['edit_person_form'] = edit_person_form
+    context["edit_person_form"] = edit_person_form
 
-    return render(request, 'core/edit_person.html', context)
+    return render(request, "core/edit_person.html", context)
 
 
 @admin_required
@@ -164,40 +164,40 @@ def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
         group = None
         edit_group_form = EditGroupForm(request.POST or None)
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if edit_group_form.is_valid():
             edit_group_form.save(commit=True)
 
-            messages.success(request, _('The group has been saved.'))
-            return redirect('groups')
+            messages.success(request, _("The group has been saved."))
+            return redirect("groups")
 
-    context['group'] = group
-    context['edit_group_form'] = edit_group_form
+    context["group"] = group
+    context["edit_group_form"] = edit_group_form
 
-    return render(request, 'core/edit_group.html', context)
+    return render(request, "core/edit_group.html", context)
 
 
 @admin_required
 def data_management(request: HttpRequest) -> HttpResponse:
     context = {}
-    return render(request, 'core/data_management.html', context)
+    return render(request, "core/data_management.html", context)
 
 
 @admin_required
 def system_status(request: HttpRequest) -> HttpResponse:
     context = {}
 
-    context['backups'] = CronJobLog.objects.filter(code='biscuit.core.Backup').order_by(
-        '-end_time'
+    context["backups"] = CronJobLog.objects.filter(code="biscuit.core.Backup").order_by(
+        "-end_time"
     )[:10]
 
-    return render(request, 'core/system_status.html', context)
+    return render(request, "core/system_status.html", context)
 
 
 @admin_required
 def school_management(request: HttpRequest) -> HttpResponse:
     context = {}
-    return render(request, 'core/school_management.html', context)
+    return render(request, "core/school_management.html", context)
 
 
 @admin_required
@@ -207,18 +207,18 @@ def edit_school(request: HttpRequest) -> HttpResponse:
     school = School.objects.first()
     edit_school_form = EditSchoolForm(request.POST or None, request.FILES or None, instance=school)
 
-    context['school'] = school
+    context["school"] = school
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if edit_school_form.is_valid():
             edit_school_form.save(commit=True)
 
-            messages.success(request, _('The school has been saved.'))
-            return redirect('index')
+            messages.success(request, _("The school has been saved."))
+            return redirect("index")
 
-    context['edit_school_form'] = edit_school_form
+    context["edit_school_form"] = edit_school_form
 
-    return render(request, 'core/edit_school.html', context)
+    return render(request, "core/edit_school.html", context)
 
 
 @admin_required
@@ -228,13 +228,13 @@ def edit_schoolterm(request: HttpRequest) -> HttpResponse:
     term = School.objects.first().current_term
     edit_term_form = EditTermForm(request.POST or None, instance=term)
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if edit_term_form.is_valid():
             edit_term_form.save(commit=True)
 
-            messages.success(request, _('The term has been saved.'))
-            return redirect('index')
+            messages.success(request, _("The term has been saved."))
+            return redirect("index")
 
-    context['edit_term_form'] = edit_term_form
+    context["edit_term_form"] = edit_term_form
 
-    return render(request, 'core/edit_schoolterm.html', context)
+    return render(request, "core/edit_schoolterm.html", context)
diff --git a/biscuit/core/wsgi.py b/biscuit/core/wsgi.py
index afb5bc6b7711d61a5160f88bea3ccc4d2e776a0d..c364569d798e00c5b4b7c178eb1554dc853101c4 100644
--- a/biscuit/core/wsgi.py
+++ b/biscuit/core/wsgi.py
@@ -2,6 +2,6 @@ import os
 
 from django.core.wsgi import get_wsgi_application
 
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'biscuit.core.settings')
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "biscuit.core.settings")
 
 application = get_wsgi_application()