diff --git a/biscuit/apps/chronos/__init__.py b/biscuit/apps/chronos/__init__.py
index 284a66af967d25ed09a77eb95c261e503d6f3974..59161f0c996b7c7ccb9f09d7e337a530a65c1fe8 100644
--- a/biscuit/apps/chronos/__init__.py
+++ b/biscuit/apps/chronos/__init__.py
@@ -1,8 +1,8 @@
 import pkg_resources
 
 try:
-    __version__ = pkg_resources.get_distribution('BiscuIT-App-Chronos').version
+    __version__ = pkg_resources.get_distribution("BiscuIT-App-Chronos").version
 except Exception:
-    __version__ = 'unknown'
+    __version__ = "unknown"
 
-default_app_config = 'biscuit.apps.chronos.apps.ChronosConfig'
+default_app_config = "biscuit.apps.chronos.apps.ChronosConfig"
diff --git a/biscuit/apps/chronos/apps.py b/biscuit/apps/chronos/apps.py
index 301742481cdc8207bde82cc28d148661d41fd062..939cc6dd011786cb36291d773068b1c236e4a76c 100644
--- a/biscuit/apps/chronos/apps.py
+++ b/biscuit/apps/chronos/apps.py
@@ -2,5 +2,5 @@ from biscuit.core.util.apps import AppConfig
 
 
 class ChronosConfig(AppConfig):
-    name = 'biscuit.apps.chronos'
-    verbose_name = 'BiscuIT - Chronos (Timetables)'
+    name = "biscuit.apps.chronos"
+    verbose_name = "BiscuIT - Chronos (Timetables)"
diff --git a/biscuit/apps/chronos/forms.py b/biscuit/apps/chronos/forms.py
index 666eb0e6c12fcd064d37980ff333e91e1a4ec242..8ee42c3aff9219766bbd4d365c7ea2d174bd4090 100644
--- a/biscuit/apps/chronos/forms.py
+++ b/biscuit/apps/chronos/forms.py
@@ -1,31 +1,51 @@
 from django import forms
 from django.db.models import Count
 from django.utils.translation import ugettext_lazy as _
+
 from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget
 
-from biscuit.core.models import Person, Group
+from biscuit.core.models import Group, Person
 
-from .models import Room, LessonSubstitution, Subject, LessonPeriod
+from .models import LessonPeriod, LessonSubstitution, Room, Subject
 
 
 class SelectForm(forms.Form):
     group = forms.ModelChoiceField(
-        queryset=Group.objects.annotate(lessons_count=Count('lessons')).filter(lessons_count__gt=0),
-        label=_('Group'), required=False, widget=Select2Widget)
+        queryset=Group.objects.annotate(lessons_count=Count("lessons")).filter(
+            lessons_count__gt=0
+        ),
+        label=_("Group"),
+        required=False,
+        widget=Select2Widget,
+    )
     teacher = forms.ModelChoiceField(
-        queryset=Person.objects.annotate(lessons_count=Count(
-            'lessons_as_teacher')).filter(lessons_count__gt=0),
-        label=_('Teacher'), required=False, widget=Select2Widget)
+        queryset=Person.objects.annotate(
+            lessons_count=Count("lessons_as_teacher")
+        ).filter(lessons_count__gt=0),
+        label=_("Teacher"),
+        required=False,
+        widget=Select2Widget,
+    )
     room = forms.ModelChoiceField(
-        queryset=Room.objects.annotate(lessons_count=Count(
-            'lesson_periods')).filter(lessons_count__gt=0),
-        label=_('Room'), required=False, widget=Select2Widget)
+        queryset=Room.objects.annotate(lessons_count=Count("lesson_periods")).filter(
+            lessons_count__gt=0
+        ),
+        label=_("Room"),
+        required=False,
+        widget=Select2Widget,
+    )
 
 
 class LessonSubstitutionForm(forms.ModelForm):
     class Meta:
         model = LessonSubstitution
-        fields = ['week', 'lesson_period', 'subject', 'teachers', 'room', 'cancelled']
+        fields = ["week", "lesson_period", "subject", "teachers", "room", "cancelled"]
         widgets = {
-            'teachers': ModelSelect2MultipleWidget(search_fields=['first_name__icontains', 'last_name__icontains', 'short_name__icontains'])
+            "teachers": ModelSelect2MultipleWidget(
+                search_fields=[
+                    "first_name__icontains",
+                    "last_name__icontains",
+                    "short_name__icontains",
+                ]
+            )
         }
diff --git a/biscuit/apps/chronos/menus.py b/biscuit/apps/chronos/menus.py
index 11851fe6cc21a3c84404b76b99a3663745486cd5..38db3e98b469ce573a4138612e727b3f95e37c3c 100644
--- a/biscuit/apps/chronos/menus.py
+++ b/biscuit/apps/chronos/menus.py
@@ -1,29 +1,32 @@
 from django.utils.translation import ugettext_lazy as _
 
 MENUS = {
-    'NAV_MENU_CORE': [
+    "NAV_MENU_CORE": [
         {
-            'name': _('Timetables'),
-            'url': '#',
-            'root': True,
-            'validators': ['menu_generator.validators.is_authenticated', 'biscuit.core.util.core_helpers.has_person'],
-            'submenu': [
+            "name": _("Timetables"),
+            "url": "#",
+            "root": True,
+            "validators": [
+                "menu_generator.validators.is_authenticated",
+                "biscuit.core.util.core_helpers.has_person",
+            ],
+            "submenu": [
                 {
-                    'name': _('Timetable'),
-                    'url': 'timetable',
-                    'validators': ['menu_generator.validators.is_authenticated']
+                    "name": _("Timetable"),
+                    "url": "timetable",
+                    "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
-                    'name': _('Daily lessons'),
-                    'url': 'lessons_day',
-                    'validators': ['menu_generator.validators.is_authenticated']
+                    "name": _("Daily lessons"),
+                    "url": "lessons_day",
+                    "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
-                    'name': _('Substitutions'),
-                    'url': 'substitutions',
-                    'validators': ['menu_generator.validators.is_authenticated']
-                }
-            ]
+                    "name": _("Substitutions"),
+                    "url": "substitutions",
+                    "validators": ["menu_generator.validators.is_authenticated"],
+                },
+            ],
         }
     ]
 }
diff --git a/biscuit/apps/chronos/migrations/0001_initial.py b/biscuit/apps/chronos/migrations/0001_initial.py
index f66c967080e791a1264bfcabe78fa362da00afd0..6ee00a6cbda2fe97d5cf47c96ee32ba2658d8c56 100644
--- a/biscuit/apps/chronos/migrations/0001_initial.py
+++ b/biscuit/apps/chronos/migrations/0001_initial.py
@@ -1,10 +1,11 @@
 # Generated by Django 2.2.5 on 2019-09-03 18:30
 
-import biscuit.apps.chronos.util
-import biscuit.core.util.core_helpers
 import django.core.validators
-from django.db import migrations, models
 import django.db.models.deletion
+from django.db import migrations, models
+
+import biscuit.apps.chronos.util
+import biscuit.core.util.core_helpers
 
 
 class Migration(migrations.Migration):
@@ -12,123 +13,335 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        ('core', '0001_initial'),
+        ("core", "0001_initial"),
     ]
 
     operations = [
         migrations.CreateModel(
-            name='Lesson',
+            name="Lesson",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('date_start', models.DateField(null=True, verbose_name='Effective start date of lesson')),
-                ('date_end', models.DateField(null=True, verbose_name='Effective end date of lesson')),
-                ('groups', models.ManyToManyField(related_name='lessons', to='core.Group')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "date_start",
+                    models.DateField(
+                        null=True, verbose_name="Effective start date of lesson"
+                    ),
+                ),
+                (
+                    "date_end",
+                    models.DateField(
+                        null=True, verbose_name="Effective end date of lesson"
+                    ),
+                ),
+                (
+                    "groups",
+                    models.ManyToManyField(related_name="lessons", to="core.Group"),
+                ),
             ],
-            options={
-                'ordering': ['date_start'],
-            },
+            options={"ordering": ["date_start"],},
         ),
         migrations.CreateModel(
-            name='LessonPeriod',
+            name="LessonPeriod",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lesson_periods', to='chronos.Lesson')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "lesson",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="lesson_periods",
+                        to="chronos.Lesson",
+                    ),
+                ),
             ],
             options={
-                'ordering': ['lesson__date_start', 'period__weekday', 'period__period'],
+                "ordering": ["lesson__date_start", "period__weekday", "period__period"],
             },
         ),
         migrations.CreateModel(
-            name='TimePeriod',
+            name="TimePeriod",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('weekday', models.PositiveSmallIntegerField(choices=[(0, 'Sunday'), (1, 'Monday'), (2, 'Tuesday'), (3, 'Wednesday'), (4, 'Thursday'), (5, 'Friday'), (6, 'Saturday')], verbose_name='Week day')),
-                ('period', models.PositiveSmallIntegerField(verbose_name='Number of period')),
-                ('time_start', models.TimeField(verbose_name='Time the period starts')),
-                ('time_end', models.TimeField(verbose_name='Time the period ends')),
-                ('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "weekday",
+                    models.PositiveSmallIntegerField(
+                        choices=[
+                            (0, "Sunday"),
+                            (1, "Monday"),
+                            (2, "Tuesday"),
+                            (3, "Wednesday"),
+                            (4, "Thursday"),
+                            (5, "Friday"),
+                            (6, "Saturday"),
+                        ],
+                        verbose_name="Week day",
+                    ),
+                ),
+                (
+                    "period",
+                    models.PositiveSmallIntegerField(verbose_name="Number of period"),
+                ),
+                ("time_start", models.TimeField(verbose_name="Time the period starts")),
+                ("time_end", models.TimeField(verbose_name="Time the period ends")),
+                (
+                    "school",
+                    models.ForeignKey(
+                        default=1,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="core.School",
+                    ),
+                ),
             ],
             options={
-                'ordering': ['weekday', 'period'],
-                'unique_together': {('school', 'weekday', 'period')},
+                "ordering": ["weekday", "period"],
+                "unique_together": {("school", "weekday", "period")},
             },
         ),
         migrations.CreateModel(
-            name='Subject',
+            name="Subject",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('abbrev', models.CharField(max_length=10, verbose_name='Abbreviation of subject in timetable')),
-                ('name', models.CharField(max_length=30, verbose_name='Long name of subject')),
-                ('colour_fg', models.CharField(blank=True, max_length=7, validators=[django.core.validators.RegexValidator('#[0-9A-F]{6}')], verbose_name='Foreground colour in timetable')),
-                ('colour_bg', models.CharField(blank=True, max_length=7, validators=[django.core.validators.RegexValidator('#[0-9A-F]{6}')], verbose_name='Background colour in timetable')),
-                ('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=10,
+                        verbose_name="Abbreviation of subject in timetable",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(
+                        max_length=30, verbose_name="Long name of subject"
+                    ),
+                ),
+                (
+                    "colour_fg",
+                    models.CharField(
+                        blank=True,
+                        max_length=7,
+                        validators=[
+                            django.core.validators.RegexValidator("#[0-9A-F]{6}")
+                        ],
+                        verbose_name="Foreground colour in timetable",
+                    ),
+                ),
+                (
+                    "colour_bg",
+                    models.CharField(
+                        blank=True,
+                        max_length=7,
+                        validators=[
+                            django.core.validators.RegexValidator("#[0-9A-F]{6}")
+                        ],
+                        verbose_name="Background colour in timetable",
+                    ),
+                ),
+                (
+                    "school",
+                    models.ForeignKey(
+                        default=1,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="core.School",
+                    ),
+                ),
             ],
             options={
-                'ordering': ['name', 'abbrev'],
-                'unique_together': {('school', 'abbrev'), ('school', 'name')},
+                "ordering": ["name", "abbrev"],
+                "unique_together": {("school", "abbrev"), ("school", "name")},
             },
         ),
         migrations.CreateModel(
-            name='Room',
+            name="Room",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('short_name', models.CharField(max_length=10, verbose_name='Short name, e.g. room number')),
-                ('name', models.CharField(max_length=30, verbose_name='Long name')),
-                ('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "short_name",
+                    models.CharField(
+                        max_length=10, verbose_name="Short name, e.g. room number"
+                    ),
+                ),
+                ("name", models.CharField(max_length=30, verbose_name="Long name")),
+                (
+                    "school",
+                    models.ForeignKey(
+                        default=1,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="core.School",
+                    ),
+                ),
             ],
             options={
-                'ordering': ['name', 'short_name'],
-                'unique_together': {('school', 'name'), ('school', 'short_name')},
+                "ordering": ["name", "short_name"],
+                "unique_together": {("school", "name"), ("school", "short_name")},
             },
         ),
         migrations.CreateModel(
-            name='LessonSubstitution',
+            name="LessonSubstitution",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('week', models.IntegerField(default=biscuit.apps.chronos.util.CalendarWeek.current_week, verbose_name='Week')),
-                ('lesson_period', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='substitutions', to='chronos.LessonPeriod')),
-                ('room', models.ForeignKey(null=True, blank=True, on_delete=django.db.models.deletion.CASCADE, to='chronos.Room', verbose_name='Room')),
-                ('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
-                ('subject', models.ForeignKey(null=True, blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='lesson_substitutions', to='chronos.Subject', verbose_name='Subject')),
-                ('teachers', models.ManyToManyField(blank=True, related_name='lesson_substitutions', to='core.Person')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "week",
+                    models.IntegerField(
+                        default=biscuit.apps.chronos.util.CalendarWeek.current_week,
+                        verbose_name="Week",
+                    ),
+                ),
+                (
+                    "lesson_period",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="substitutions",
+                        to="chronos.LessonPeriod",
+                    ),
+                ),
+                (
+                    "room",
+                    models.ForeignKey(
+                        null=True,
+                        blank=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="chronos.Room",
+                        verbose_name="Room",
+                    ),
+                ),
+                (
+                    "school",
+                    models.ForeignKey(
+                        default=1,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="core.School",
+                    ),
+                ),
+                (
+                    "subject",
+                    models.ForeignKey(
+                        null=True,
+                        blank=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="lesson_substitutions",
+                        to="chronos.Subject",
+                        verbose_name="Subject",
+                    ),
+                ),
+                (
+                    "teachers",
+                    models.ManyToManyField(
+                        blank=True,
+                        related_name="lesson_substitutions",
+                        to="core.Person",
+                    ),
+                ),
             ],
             options={
-                'ordering': ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday', 'lesson_period__period__period'],
+                "ordering": [
+                    "lesson_period__lesson__date_start",
+                    "week",
+                    "lesson_period__period__weekday",
+                    "lesson_period__period__period",
+                ],
             },
         ),
         migrations.AddField(
-            model_name='lessonperiod',
-            name='period',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lesson_periods', to='chronos.TimePeriod'),
+            model_name="lessonperiod",
+            name="period",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="lesson_periods",
+                to="chronos.TimePeriod",
+            ),
         ),
         migrations.AddField(
-            model_name='lessonperiod',
-            name='room',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='lesson_periods', to='chronos.Room'),
+            model_name="lessonperiod",
+            name="room",
+            field=models.ForeignKey(
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="lesson_periods",
+                to="chronos.Room",
+            ),
         ),
         migrations.AddField(
-            model_name='lessonperiod',
-            name='school',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School'),
+            model_name="lessonperiod",
+            name="school",
+            field=models.ForeignKey(
+                default=1, on_delete=django.db.models.deletion.CASCADE, to="core.School"
+            ),
         ),
         migrations.AddField(
-            model_name='lesson',
-            name='periods',
-            field=models.ManyToManyField(related_name='lessons', through='chronos.LessonPeriod', to='chronos.TimePeriod'),
+            model_name="lesson",
+            name="periods",
+            field=models.ManyToManyField(
+                related_name="lessons",
+                through="chronos.LessonPeriod",
+                to="chronos.TimePeriod",
+            ),
         ),
         migrations.AddField(
-            model_name='lesson',
-            name='school',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School'),
+            model_name="lesson",
+            name="school",
+            field=models.ForeignKey(
+                default=1, on_delete=django.db.models.deletion.CASCADE, to="core.School"
+            ),
         ),
         migrations.AddField(
-            model_name='lesson',
-            name='subject',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lessons', to='chronos.Subject'),
+            model_name="lesson",
+            name="subject",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="lessons",
+                to="chronos.Subject",
+            ),
         ),
         migrations.AddField(
-            model_name='lesson',
-            name='teachers',
-            field=models.ManyToManyField(related_name='lessons', to='core.Person'),
+            model_name="lesson",
+            name="teachers",
+            field=models.ManyToManyField(related_name="lessons", to="core.Person"),
         ),
     ]
diff --git a/biscuit/apps/chronos/migrations/0002_db_indexes.py b/biscuit/apps/chronos/migrations/0002_db_indexes.py
index 49be25b9145eb526bcfa3c6aec74415fc6d6034b..f6ee2fe1cf4fd021c8c1c00b75f6d349b3f3978c 100644
--- a/biscuit/apps/chronos/migrations/0002_db_indexes.py
+++ b/biscuit/apps/chronos/migrations/0002_db_indexes.py
@@ -6,25 +6,31 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('core', '0001_initial'),
-        ('chronos', '0001_initial'),
+        ("core", "0001_initial"),
+        ("chronos", "0001_initial"),
     ]
 
     operations = [
         migrations.AlterUniqueTogether(
-            name='lessonsubstitution',
-            unique_together={('school', 'lesson_period', 'week')},
+            name="lessonsubstitution",
+            unique_together={("school", "lesson_period", "week")},
         ),
         migrations.AddIndex(
-            model_name='lesson',
-            index=models.Index(fields=['date_start', 'date_end'], name='chronos_les_date_st_5ecc62_idx'),
+            model_name="lesson",
+            index=models.Index(
+                fields=["date_start", "date_end"], name="chronos_les_date_st_5ecc62_idx"
+            ),
         ),
         migrations.AddIndex(
-            model_name='lessonperiod',
-            index=models.Index(fields=['lesson', 'period'], name='chronos_les_lesson__05250e_idx'),
+            model_name="lessonperiod",
+            index=models.Index(
+                fields=["lesson", "period"], name="chronos_les_lesson__05250e_idx"
+            ),
         ),
         migrations.AddIndex(
-            model_name='timeperiod',
-            index=models.Index(fields=['time_start', 'time_end'], name='chronos_tim_time_st_491e4c_idx'),
+            model_name="timeperiod",
+            index=models.Index(
+                fields=["time_start", "time_end"], name="chronos_tim_time_st_491e4c_idx"
+            ),
         ),
     ]
diff --git a/biscuit/apps/chronos/migrations/0003_substitution_cancelled_or_subject.py b/biscuit/apps/chronos/migrations/0003_substitution_cancelled_or_subject.py
index 7f53974affeec61b9164028cfa3b4447345aae5c..a7486e4702fadab910c7e59e230ffbffca20ea30 100644
--- a/biscuit/apps/chronos/migrations/0003_substitution_cancelled_or_subject.py
+++ b/biscuit/apps/chronos/migrations/0003_substitution_cancelled_or_subject.py
@@ -6,17 +6,22 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('chronos', '0002_db_indexes'),
+        ("chronos", "0002_db_indexes"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='lessonsubstitution',
-            name='cancelled',
+            model_name="lessonsubstitution",
+            name="cancelled",
             field=models.BooleanField(default=False),
         ),
         migrations.AddConstraint(
-            model_name='lessonsubstitution',
-            constraint=models.CheckConstraint(check=models.Q(('cancelled', True), ('subject__isnull', False), _negated=True), name='either_substituted_or_cancelled'),
+            model_name="lessonsubstitution",
+            constraint=models.CheckConstraint(
+                check=models.Q(
+                    ("cancelled", True), ("subject__isnull", False), _negated=True
+                ),
+                name="either_substituted_or_cancelled",
+            ),
         ),
     ]
diff --git a/biscuit/apps/chronos/migrations/0004_room_name_not_unique.py b/biscuit/apps/chronos/migrations/0004_room_name_not_unique.py
index 241ea2db5ff8d9d81ff49924543b4e9ec840a4d2..c862d32086b74b71c9a1715f53993a82623e3e48 100644
--- a/biscuit/apps/chronos/migrations/0004_room_name_not_unique.py
+++ b/biscuit/apps/chronos/migrations/0004_room_name_not_unique.py
@@ -6,12 +6,11 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('chronos', '0003_substitution_cancelled_or_subject'),
+        ("chronos", "0003_substitution_cancelled_or_subject"),
     ]
 
     operations = [
         migrations.AlterUniqueTogether(
-            name='room',
-            unique_together={('school', 'short_name')},
+            name="room", unique_together={("school", "short_name")},
         ),
     ]
diff --git a/biscuit/apps/chronos/models.py b/biscuit/apps/chronos/models.py
index f3594aaf6fcbd051a517aa4c47d642b6521c0022..a380c6770c4930eda235058ae82173137e7abb48 100644
--- a/biscuit/apps/chronos/models.py
+++ b/biscuit/apps/chronos/models.py
@@ -22,10 +22,11 @@ class LessonPeriodManager(models.Manager):
     def get_queryset(self):
         """ Ensures all related lesson data is loaded as well. """
 
-        return super().get_queryset().select_related(
-            'lesson', 'lesson__subject', 'period', 'room'
-        ).prefetch_related(
-            'lesson__groups', 'lesson__teachers', 'substitutions'
+        return (
+            super()
+            .get_queryset()
+            .select_related("lesson", "lesson__subject", "period", "room")
+            .prefetch_related("lesson__groups", "lesson__teachers", "substitutions")
         )
 
 
@@ -41,8 +42,8 @@ class LessonPeriodQuerySet(models.QuerySet):
         """ Filter for all lessons within a calendar week. """
 
         return self.within_dates(
-            wanted_week[0] + timedelta(days=1) * (models.F('period__weekday') - 1),
-            wanted_week[0] + timedelta(days=1) * (models.F('period__weekday') - 1)
+            wanted_week[0] + timedelta(days=1) * (models.F("period__weekday") - 1),
+            wanted_week[0] + timedelta(days=1) * (models.F("period__weekday") - 1),
         ).annotate_week(wanted_week)
 
     def on_day(self, day: date):
@@ -50,9 +51,11 @@ class LessonPeriodQuerySet(models.QuerySet):
 
         week, weekday = week_weekday_from_date(day)
 
-        return self.within_dates(day, day).filter(
-            period__weekday=weekday
-        ).annotate_week(week)
+        return (
+            self.within_dates(day, day)
+            .filter(period__weekday=weekday)
+            .annotate_week(week)
+        )
 
     def at_time(self, when: Optional[datetime] = None):
         """ Filter for the lessons taking place at a certain point in time. """
@@ -65,32 +68,39 @@ class LessonPeriodQuerySet(models.QuerySet):
             lesson__date_end__gte=now.date(),
             period__weekday=now.isoweekday(),
             period__time_start__lte=now.time(),
-            period__time_end__gte=now.time()
+            period__time_end__gte=now.time(),
         ).annotate_week(week)
 
     def filter_participant(self, person: Union[Person, int]):
         """ Filter for all lessons a participant (student) attends. """
 
         return self.filter(
-            Q(lesson__groups__members=person) | Q(lesson__groups__parent_groups__members=person))
+            Q(lesson__groups__members=person)
+            | Q(lesson__groups__parent_groups__members=person)
+        )
 
     def filter_group(self, group: Union[Group, int]):
         """ Filter for all lessons a group (class) regularly attends. """
 
         return self.filter(
-            Q(lesson__groups=group) | Q(lesson__groups__parent_groups=group))
+            Q(lesson__groups=group) | Q(lesson__groups__parent_groups=group)
+        )
 
     def filter_teacher(self, teacher: Union[Person, int]):
         """ Filter for all lessons given by a certain teacher. """
 
         return self.filter(
-            Q(substitutions__teachers=teacher, substitutions__week=models.F('_week')) | Q(lesson__teachers=teacher))
+            Q(substitutions__teachers=teacher, substitutions__week=models.F("_week"))
+            | Q(lesson__teachers=teacher)
+        )
 
     def filter_room(self, room: Union[Room, int]):
         """ Filter for all lessons taking part in a certain room. """
 
         return self.filter(
-            Q(substitutions__room=room, substitutions__week=models.F('_week')) | Q(room=room))
+            Q(substitutions__room=room, substitutions__week=models.F("_week"))
+            | Q(room=room)
+        )
 
     def annotate_week(self, week: Union[CalendarWeek, int]):
         """ Annotate all lessons in the QuerySet with the number of the provided calendar week. """
@@ -100,9 +110,7 @@ class LessonPeriodQuerySet(models.QuerySet):
         else:
             week_num = week
 
-        return self.annotate(
-            _week=models.Value(week_num, models.IntegerField())
-        )
+        return self.annotate(_week=models.Value(week_num, models.IntegerField()))
 
     def next(self, reference: LessonPeriod, offset: Optional[int] = 1) -> LessonPeriod:
         """ Get another lesson in an ordered set of lessons.
@@ -112,7 +120,7 @@ class LessonPeriodQuerySet(models.QuerySet):
         previous lesson can be selected.
         """
 
-        index = list(self.values_list('id', flat=True)).index(reference.id)
+        index = list(self.values_list("id", flat=True)).index(reference.id)
 
         next_index = index + offset
         if next_index > self.count() - 1:
@@ -132,35 +140,40 @@ class LessonPeriodQuerySet(models.QuerySet):
         All three fields are filtered, in order.
         """
 
-        if query_data.get('group', None):
-            return self.filter_group(int(query_data['group']))
-        if query_data.get('teacher', None):
-            return self.filter_teacher(int(query_data['teacher']))
-        if query_data.get('room', None):
-            return self.filter_room(int(query_data['room']))
+        if query_data.get("group", None):
+            return self.filter_group(int(query_data["group"]))
+        if query_data.get("teacher", None):
+            return self.filter_teacher(int(query_data["teacher"]))
+        if query_data.get("room", None):
+            return self.filter_room(int(query_data["room"]))
 
 
 class TimePeriod(models.Model):
     WEEKDAY_CHOICES = [
-        (0, _('Sunday')),
-        (1, _('Monday')),
-        (2, _('Tuesday')),
-        (3, _('Wednesday')),
-        (4, _('Thursday')),
-        (5, _('Friday')),
-        (6, _('Saturday'))
+        (0, _("Sunday")),
+        (1, _("Monday")),
+        (2, _("Tuesday")),
+        (3, _("Wednesday")),
+        (4, _("Thursday")),
+        (5, _("Friday")),
+        (6, _("Saturday")),
     ]
 
-    weekday = models.PositiveSmallIntegerField(verbose_name=_(
-        'Week day'), choices=WEEKDAY_CHOICES)
-    period = models.PositiveSmallIntegerField(
-        verbose_name=_('Number of period'))
+    weekday = models.PositiveSmallIntegerField(
+        verbose_name=_("Week day"), choices=WEEKDAY_CHOICES
+    )
+    period = models.PositiveSmallIntegerField(verbose_name=_("Number of period"))
 
-    time_start = models.TimeField(verbose_name=_('Time the period starts'))
-    time_end = models.TimeField(verbose_name=_('Time the period ends'))
+    time_start = models.TimeField(verbose_name=_("Time the period starts"))
+    time_end = models.TimeField(verbose_name=_("Time the period ends"))
 
     def __str__(self) -> str:
-        return '%s, %d. period (%s - %s)' % (self.weekday, self.period, self.time_start, self.time_end)
+        return "%s, %d. period (%s - %s)" % (
+            self.weekday,
+            self.period,
+            self.time_start,
+            self.time_end,
+        )
 
     @classmethod
     def get_times_dict(cls) -> Dict[int, Tuple[datetime, datetime]]:
@@ -175,113 +188,143 @@ class TimePeriod(models.Model):
             wanted_week = week
         else:
             year = date.today().year
-            week_number = week or getattr(self, '_week', None) or CalendarWeek().week
+            week_number = week or getattr(self, "_week", None) or CalendarWeek().week
 
             if week_number < self.school.current_term.date_start.isocalendar()[1]:
                 year += 1
 
             wanted_week = CalendarWeek(year=year, week=week_number)
 
-        return wanted_week[self.weekday-1]
+        return wanted_week[self.weekday - 1]
 
     class Meta:
-        unique_together = [['weekday', 'period']]
-        ordering = ['weekday', 'period']
-        indexes = [models.Index(fields=['time_start', 'time_end'])]
+        unique_together = [["weekday", "period"]]
+        ordering = ["weekday", "period"]
+        indexes = [models.Index(fields=["time_start", "time_end"])]
 
 
 class Subject(models.Model):
-    abbrev = models.CharField(verbose_name=_(
-        'Abbreviation of subject in timetable'), max_length=10, unique=True)
-    name = models.CharField(verbose_name=_(
-        'Long name of subject'), max_length=30, unique=True)
-
-    colour_fg = models.CharField(verbose_name=_('Foreground colour in timetable'), blank=True, validators=[
-                                 validators.RegexValidator(r'#[0-9A-F]{6}')], max_length=7)
-    colour_bg = models.CharField(verbose_name=_('Background colour in timetable'), blank=True, validators=[
-                                 validators.RegexValidator(r'#[0-9A-F]{6}')], max_length=7)
+    abbrev = models.CharField(
+        verbose_name=_("Abbreviation of subject in timetable"),
+        max_length=10,
+        unique=True,
+    )
+    name = models.CharField(
+        verbose_name=_("Long name of subject"), max_length=30, unique=True
+    )
+
+    colour_fg = models.CharField(
+        verbose_name=_("Foreground colour in timetable"),
+        blank=True,
+        validators=[validators.RegexValidator(r"#[0-9A-F]{6}")],
+        max_length=7,
+    )
+    colour_bg = models.CharField(
+        verbose_name=_("Background colour in timetable"),
+        blank=True,
+        validators=[validators.RegexValidator(r"#[0-9A-F]{6}")],
+        max_length=7,
+    )
 
     def __str__(self) -> str:
-        return '%s - %s' % (self.abbrev, self.name)
+        return "%s - %s" % (self.abbrev, self.name)
 
     class Meta:
-        ordering = ['name', 'abbrev']
+        ordering = ["name", "abbrev"]
 
 
 class Room(models.Model):
-    short_name = models.CharField(verbose_name=_(
-        'Short name, e.g. room number'), max_length=10, unique=True)
-    name = models.CharField(verbose_name=_('Long name'),
-                            max_length=30)
+    short_name = models.CharField(
+        verbose_name=_("Short name, e.g. room number"), max_length=10, unique=True
+    )
+    name = models.CharField(verbose_name=_("Long name"), max_length=30)
 
     def __str__(self) -> str:
-        return '%s (%s)' % (self.name, self.short_name)
+        return "%s (%s)" % (self.name, self.short_name)
 
     class Meta:
-        ordering = ['name', 'short_name']
+        ordering = ["name", "short_name"]
 
 
 class Lesson(models.Model):
     subject = models.ForeignKey(
-        'Subject', on_delete=models.CASCADE, related_name='lessons')
-    teachers = models.ManyToManyField('core.Person', related_name='lessons_as_teacher')
+        "Subject", on_delete=models.CASCADE, related_name="lessons"
+    )
+    teachers = models.ManyToManyField("core.Person", related_name="lessons_as_teacher")
     periods = models.ManyToManyField(
-        'TimePeriod', related_name='lessons', through='LessonPeriod')
-    groups = models.ManyToManyField('core.Group', related_name='lessons')
+        "TimePeriod", related_name="lessons", through="LessonPeriod"
+    )
+    groups = models.ManyToManyField("core.Group", related_name="lessons")
 
-    date_start = models.DateField(verbose_name=_(
-        'Effective start date of lesson'), null=True)
-    date_end = models.DateField(verbose_name=_(
-        'Effective end date of lesson'), null=True)
+    date_start = models.DateField(
+        verbose_name=_("Effective start date of lesson"), null=True
+    )
+    date_end = models.DateField(
+        verbose_name=_("Effective end date of lesson"), null=True
+    )
 
     @property
-    def teacher_names(self, sep: Optional[str] = ', ') -> str:
+    def teacher_names(self, sep: Optional[str] = ", ") -> str:
         return sep.join([teacher.full_name for teacher in self.teachers.all()])
 
     @property
-    def group_names(self, sep: Optional[str] = ', ') -> str:
+    def group_names(self, sep: Optional[str] = ", ") -> str:
         return sep.join([group.short_name for group in self.groups.all()])
 
     def get_calendar_week(self, week: int):
         year = self.date_start.year
-        if week < int(self.date_start.strftime('%V')):
+        if week < int(self.date_start.strftime("%V")):
             year += 1
 
         return CalendarWeek(year=year, week=week)
 
     class Meta:
-        ordering = ['date_start']
-        indexes = [models.Index(fields=['date_start', 'date_end'])]
+        ordering = ["date_start"]
+        indexes = [models.Index(fields=["date_start", "date_end"])]
 
 
 class LessonSubstitution(models.Model):
-    week = models.IntegerField(verbose_name=_('Week'),
-                               default=CalendarWeek.current_week)
+    week = models.IntegerField(
+        verbose_name=_("Week"), default=CalendarWeek.current_week
+    )
 
-    lesson_period = models.ForeignKey(
-        'LessonPeriod', models.CASCADE, 'substitutions')
+    lesson_period = models.ForeignKey("LessonPeriod", models.CASCADE, "substitutions")
 
     subject = models.ForeignKey(
-        'Subject', on_delete=models.CASCADE,
-        related_name='lesson_substitutions', null=True, blank=True, verbose_name=_('Subject'))
-    teachers = models.ManyToManyField('core.Person',
-                                      related_name='lesson_substitutions', blank=True)
-    room = models.ForeignKey('Room', models.CASCADE, null=True, blank=True, verbose_name=_('Room'))
+        "Subject",
+        on_delete=models.CASCADE,
+        related_name="lesson_substitutions",
+        null=True,
+        blank=True,
+        verbose_name=_("Subject"),
+    )
+    teachers = models.ManyToManyField(
+        "core.Person", related_name="lesson_substitutions", blank=True
+    )
+    room = models.ForeignKey(
+        "Room", models.CASCADE, null=True, blank=True, verbose_name=_("Room")
+    )
 
     cancelled = models.BooleanField(default=False)
 
     def clean(self) -> None:
         if self.subject and self.cancelled:
-            raise ValidationError(_('Lessons can only be either substituted or cancelled.'))
+            raise ValidationError(
+                _("Lessons can only be either substituted or cancelled.")
+            )
 
     class Meta:
-        unique_together = [['lesson_period', 'week']]
-        ordering = ['lesson_period__lesson__date_start', 'week',
-                    'lesson_period__period__weekday', 'lesson_period__period__period']
+        unique_together = [["lesson_period", "week"]]
+        ordering = [
+            "lesson_period__lesson__date_start",
+            "week",
+            "lesson_period__period__weekday",
+            "lesson_period__period__period",
+        ]
         constraints = [
             models.CheckConstraint(
                 check=~Q(cancelled=True, subject__isnull=False),
-                name='either_substituted_or_cancelled'
+                name="either_substituted_or_cancelled",
             )
         ]
 
@@ -289,13 +332,17 @@ class LessonSubstitution(models.Model):
 class LessonPeriod(models.Model, ExtensibleModel):
     objects = LessonPeriodManager.from_queryset(LessonPeriodQuerySet)()
 
-    lesson = models.ForeignKey('Lesson', models.CASCADE, related_name='lesson_periods')
-    period = models.ForeignKey('TimePeriod', models.CASCADE, related_name='lesson_periods')
+    lesson = models.ForeignKey("Lesson", models.CASCADE, related_name="lesson_periods")
+    period = models.ForeignKey(
+        "TimePeriod", models.CASCADE, related_name="lesson_periods"
+    )
 
-    room = models.ForeignKey('Room', models.CASCADE, null=True, related_name='lesson_periods')
+    room = models.ForeignKey(
+        "Room", models.CASCADE, null=True, related_name="lesson_periods"
+    )
 
     def get_substitution(self, week: Optional[int] = None) -> LessonSubstitution:
-        wanted_week = week or getattr(self, '_week', None) or CalendarWeek().week
+        wanted_week = week or getattr(self, "_week", None) or CalendarWeek().week
 
         # We iterate over all substitutions because this can make use of
         # prefetching when this model is loaded from outside, in contrast
@@ -323,17 +370,20 @@ class LessonPeriod(models.Model, ExtensibleModel):
         else:
             return self.room
 
-    def get_teacher_names(self, sep: Optional[str] = ', ') -> str:
+    def get_teacher_names(self, sep: Optional[str] = ", ") -> str:
         return sep.join([teacher.full_name for teacher in self.get_teachers().all()])
 
     def get_groups(self) -> models.query.QuerySet:
         return self.lesson.groups
 
     def __str__(self) -> str:
-        return '%s, %d., %s, %s' % (self.period.get_weekday_display(), self.period.period,
-                                    ', '.join(list(self.lesson.groups.values_list('short_name', flat=True))),
-                                    self.lesson.subject.name)
+        return "%s, %d., %s, %s" % (
+            self.period.get_weekday_display(),
+            self.period.period,
+            ", ".join(list(self.lesson.groups.values_list("short_name", flat=True))),
+            self.lesson.subject.name,
+        )
 
     class Meta:
-        ordering = ['lesson__date_start', 'period__weekday', 'period__period']
-        indexes = [models.Index(fields=['lesson', 'period'])]
+        ordering = ["lesson__date_start", "period__weekday", "period__period"]
+        indexes = [models.Index(fields=["lesson", "period"])]
diff --git a/biscuit/apps/chronos/tables.py b/biscuit/apps/chronos/tables.py
index f05d6aa13cbae38d939b7b038a62132ab571a599..fd663e9cbf6476e4b78671a42857d145c6902113 100644
--- a/biscuit/apps/chronos/tables.py
+++ b/biscuit/apps/chronos/tables.py
@@ -3,43 +3,59 @@ from __future__ import annotations
 from typing import Optional
 
 from django.utils.translation import ugettext_lazy as _
+
 import django_tables2 as tables
 from django_tables2.utils import A
 
 from .models import LessonPeriod
 
 
-def _css_class_from_lesson_state(record: Optional[LessonPeriod] = None, table: Optional[LessonsTable] = None) -> str:
+def _css_class_from_lesson_state(
+    record: Optional[LessonPeriod] = None, table: Optional[LessonsTable] = None
+) -> str:
     if record.get_substitution(record._week):
         if record.get_substitution(record._week).cancelled:
-            return 'table-danger'
+            return "table-danger"
         else:
-            return 'table-warning'
+            return "table-warning"
     else:
-        return ''
+        return ""
 
 
 class LessonsTable(tables.Table):
     class Meta:
-        attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'}
-        row_attrs = {'class': _css_class_from_lesson_state}
-
-    period__period = tables.Column(accessor='period.period')
-    lesson__groups = tables.Column(accessor='lesson.group_names', verbose_name=_('Groups'))
-    lesson__teachers = tables.Column(accessor='lesson.teacher_names', verbose_name=_('Teachers'))
-    lesson__subject = tables.Column(accessor='lesson.subject')
-    room = tables.Column(accessor='room')
+        attrs = {
+            "class": "table table-striped table-bordered table-hover table-responsive-xl"
+        }
+        row_attrs = {"class": _css_class_from_lesson_state}
+
+    period__period = tables.Column(accessor="period.period")
+    lesson__groups = tables.Column(
+        accessor="lesson.group_names", verbose_name=_("Groups")
+    )
+    lesson__teachers = tables.Column(
+        accessor="lesson.teacher_names", verbose_name=_("Teachers")
+    )
+    lesson__subject = tables.Column(accessor="lesson.subject")
+    room = tables.Column(accessor="room")
     edit_substitution = tables.LinkColumn(
-        'edit_substitution', args=[A('id'), A('_week')], text=_('Substitution'))
+        "edit_substitution", args=[A("id"), A("_week")], text=_("Substitution")
+    )
 
 
 class SubstitutionsTable(tables.Table):
     class Meta:
-        attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'}
-
-    lesson_period = tables.Column(verbose_name=_('Lesson'))
-    lesson__groups = tables.Column(accessor='lesson_period.lesson.group_names', verbose_name=_('Groups'))
-    lesson__teachers = tables.Column(accessor='lesson_period.get_teacher_names', verbose_name=_('Teachers'))
-    lesson__subject = tables.Column(accessor='subject')
-    room = tables.Column(accessor='room')
-    cancelled = tables.BooleanColumn(accessor='cancelled', verbose_name=_('Cancelled'))
+        attrs = {
+            "class": "table table-striped table-bordered table-hover table-responsive-xl"
+        }
+
+    lesson_period = tables.Column(verbose_name=_("Lesson"))
+    lesson__groups = tables.Column(
+        accessor="lesson_period.lesson.group_names", verbose_name=_("Groups")
+    )
+    lesson__teachers = tables.Column(
+        accessor="lesson_period.get_teacher_names", verbose_name=_("Teachers")
+    )
+    lesson__subject = tables.Column(accessor="subject")
+    room = tables.Column(accessor="room")
+    cancelled = tables.BooleanColumn(accessor="cancelled", verbose_name=_("Cancelled"))
diff --git a/biscuit/apps/chronos/templatetags/week_helpers.py b/biscuit/apps/chronos/templatetags/week_helpers.py
index 20e19d222ae6ae2a95326dfb20e9e1aab287fcc9..529d253ae7b9a66879598c794650820358aac29c 100644
--- a/biscuit/apps/chronos/templatetags/week_helpers.py
+++ b/biscuit/apps/chronos/templatetags/week_helpers.py
@@ -4,8 +4,7 @@ from typing import Optional, Union
 from django import template
 from django.db.models.query import QuerySet
 
-from ..util import CalendarWeek, week_weekday_to_date, week_period_to_date
-
+from ..util import CalendarWeek, week_period_to_date, week_weekday_to_date
 
 register = template.Library()
 
diff --git a/biscuit/apps/chronos/urls.py b/biscuit/apps/chronos/urls.py
index f567ab33cefb5996f357ba1d768a63b8071e3d1c..c3c8157dd3bc9f28367d51c917ed1494adb88376 100644
--- a/biscuit/apps/chronos/urls.py
+++ b/biscuit/apps/chronos/urls.py
@@ -2,14 +2,25 @@ from django.urls import path
 
 from . import views
 
-
 urlpatterns = [
-    path('timetable', views.timetable, name='timetable'),
-    path('timetable/<int:year>/<int:week>', views.timetable, name='timetable_by_week'),
-    path('lessons', views.lessons_day, name='lessons_day'),
-    path('lessons/<when>', views.lessons_day, name='lessons_day_by_date'),
-    path('lessons/<int:id_>/<int:week>/substition', views.edit_substitution, name='edit_substitution'),
-    path('lessons/<int:id_>/<int:week>/substition/delete', views.delete_substitution, name='delete_substitution'),
-    path('substitutions', views.substitutions, name='substitutions'),
-    path('substitutions/<int:year>/<int:week>', views.substitutions, name='substitutions_by_week')
+    path("timetable", views.timetable, name="timetable"),
+    path("timetable/<int:year>/<int:week>", views.timetable, name="timetable_by_week"),
+    path("lessons", views.lessons_day, name="lessons_day"),
+    path("lessons/<when>", views.lessons_day, name="lessons_day_by_date"),
+    path(
+        "lessons/<int:id_>/<int:week>/substition",
+        views.edit_substitution,
+        name="edit_substitution",
+    ),
+    path(
+        "lessons/<int:id_>/<int:week>/substition/delete",
+        views.delete_substitution,
+        name="delete_substitution",
+    ),
+    path("substitutions", views.substitutions, name="substitutions"),
+    path(
+        "substitutions/<int:year>/<int:week>",
+        views.substitutions,
+        name="substitutions_by_week",
+    ),
 ]
diff --git a/biscuit/apps/chronos/util.py b/biscuit/apps/chronos/util.py
index ccbeaf144034d1a449f559995cfcf78cc48d2276..300838bc8d44b8b14a1f8313f26dfe63420ad1da 100644
--- a/biscuit/apps/chronos/util.py
+++ b/biscuit/apps/chronos/util.py
@@ -20,7 +20,7 @@ class CalendarWeek:
     def from_date(cls, when: date):
         """ Get the calendar week by a date object (the week this date is in). """
 
-        return cls(year=when.year, week=int(when.strftime('%V')))
+        return cls(year=when.year, week=int(when.strftime("%V")))
 
     @classmethod
     def current_week(cls) -> int:
@@ -33,7 +33,7 @@ class CalendarWeek:
         """ Get all calendar weeks within a date range. """
 
         if start > end:
-            raise ValueError('End date must be after start date.')
+            raise ValueError("End date must be after start date.")
 
         current = start
         weeks = []
@@ -49,22 +49,30 @@ class CalendarWeek:
         if not self.year:
             self.year = today.year
         if not self.week:
-            self.week = int(today.strftime('%V'))
+            self.week = int(today.strftime("%V"))
 
     def __str__(self) -> str:
-        return '%s %d (%s %s %s)' % (_('Calendar Week'), self.week, self[0], _('to'), self[-1])
+        return "%s %d (%s %s %s)" % (
+            _("Calendar Week"),
+            self.week,
+            self[0],
+            _("to"),
+            self[-1],
+        )
 
     def __len__(self) -> int:
         return 7
 
     def __getitem__(self, n: int) -> date:
         if n < -7 or n > 6:
-            raise IndexError('Week day %d is out of range.' % n)
+            raise IndexError("Week day %d is out of range." % n)
 
         if n < 0:
             n += 7
 
-        return datetime.strptime('%d-%d-%d' % (self.year, self.week, n + 1), '%G-%V-%u').date()
+        return datetime.strptime(
+            "%d-%d-%d" % (self.year, self.week, n + 1), "%G-%V-%u"
+        ).date()
 
     def __contains__(self, day: date) -> bool:
         return self.__class__.form_date(day) == self
diff --git a/biscuit/apps/chronos/views.py b/biscuit/apps/chronos/views.py
index f388891463742628250e87889d6c822c35a864f5..dce61cff3b1c7404dc51f8b9f36b86f16e7e7034 100644
--- a/biscuit/apps/chronos/views.py
+++ b/biscuit/apps/chronos/views.py
@@ -1,5 +1,5 @@
-from datetime import date, datetime, timedelta
 from collections import OrderedDict
+from datetime import date, datetime, timedelta
 from typing import Optional
 
 from django.contrib.auth.decorators import login_required
@@ -14,14 +14,16 @@ from django_tables2 import RequestConfig
 from biscuit.core.decorators import admin_required
 from biscuit.core.util import messages
 
-from .forms import SelectForm, LessonSubstitutionForm
-from .models import LessonPeriod, TimePeriod, LessonSubstitution
-from .util import CalendarWeek
+from .forms import LessonSubstitutionForm, SelectForm
+from .models import LessonPeriod, LessonSubstitution, TimePeriod
 from .tables import LessonsTable, SubstitutionsTable
+from .util import CalendarWeek
 
 
 @login_required
-def timetable(request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None) -> HttpResponse:
+def timetable(
+    request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None
+) -> HttpResponse:
     context = {}
 
     if year and week:
@@ -32,60 +34,77 @@ def timetable(request: HttpRequest, year: Optional[int] = None, week: Optional[i
     lesson_periods = LessonPeriod.objects.in_week(wanted_week)
 
     # Incrementally filter lesson periods by GET parameters
-    if request.GET.get('group', None) or request.GET.get('teacher', None) or request.GET.get('room', None):
+    if (
+        request.GET.get("group", None)
+        or request.GET.get("teacher", None)
+        or request.GET.get("room", None)
+    ):
         lesson_periods = lesson_periods.filter_from_query(request.GET)
     else:
         # Redirect to a selected view if no filter provided
         if request.user.person:
             if request.user.person.primary_group:
-                return redirect(reverse('timetable') + '?group=%d' % request.user.person.primary_group.pk)
+                return redirect(
+                    reverse("timetable")
+                    + "?group=%d" % request.user.person.primary_group.pk
+                )
             elif lesson_periods.filter(lesson__teachers=request.user.person).exists():
-                return redirect(reverse('timetable') + '?teacher=%d' % request.user.person.pk)
+                return redirect(
+                    reverse("timetable") + "?teacher=%d" % request.user.person.pk
+                )
 
     # Regroup lesson periods per weekday
     per_day = {}
     for lesson_period in lesson_periods:
-        per_day.setdefault(lesson_period.period.weekday,
-                           {})[lesson_period.period.period] = lesson_period
+        per_day.setdefault(lesson_period.period.weekday, {})[
+            lesson_period.period.period
+        ] = lesson_period
 
     # Determine overall first and last day and period
     min_max = TimePeriod.objects.aggregate(
-        Min('period'), Max('period'),
-        Min('weekday'), Max('weekday'))
+        Min("period"), Max("period"), Min("weekday"), Max("weekday")
+    )
 
     # Fill in empty lessons
-    for weekday_num in range(min_max.get('weekday__min', 0),
-                             min_max.get('weekday__max', 6) + 1):
+    for weekday_num in range(
+        min_max.get("weekday__min", 0), min_max.get("weekday__max", 6) + 1
+    ):
         # Fill in empty weekdays
         if weekday_num not in per_day.keys():
             per_day[weekday_num] = {}
 
         # Fill in empty lessons on this workday
-        for period_num in range(min_max.get('period__min', 1),
-                                min_max.get('period__max', 7) + 1):
+        for period_num in range(
+            min_max.get("period__min", 1), min_max.get("period__max", 7) + 1
+        ):
             if period_num not in per_day[weekday_num].keys():
                 per_day[weekday_num][period_num] = None
 
         # Order this weekday by periods
-        per_day[weekday_num] = OrderedDict(
-            sorted(per_day[weekday_num].items()))
+        per_day[weekday_num] = OrderedDict(sorted(per_day[weekday_num].items()))
 
     # Add a form to filter the view
     select_form = SelectForm(request.GET or None)
 
-    context['current_head'] = _('Timetable')
-    context['lesson_periods'] = OrderedDict(sorted(per_day.items()))
-    context['periods'] = TimePeriod.get_times_dict()
-    context['weekdays'] = dict(TimePeriod.WEEKDAY_CHOICES)
-    context['week'] = wanted_week
-    context['select_form'] = select_form
+    context["current_head"] = _("Timetable")
+    context["lesson_periods"] = OrderedDict(sorted(per_day.items()))
+    context["periods"] = TimePeriod.get_times_dict()
+    context["weekdays"] = dict(TimePeriod.WEEKDAY_CHOICES)
+    context["week"] = wanted_week
+    context["select_form"] = select_form
 
     week_prev = wanted_week - 1
     week_next = wanted_week + 1
-    context['url_prev'] = '%s?%s' % (reverse('timetable_by_week', args=[week_prev.year, week_prev.week]), request.GET.urlencode())
-    context['url_next'] = '%s?%s' % (reverse('timetable_by_week', args=[week_next.year, week_next.week]), request.GET.urlencode())
+    context["url_prev"] = "%s?%s" % (
+        reverse("timetable_by_week", args=[week_prev.year, week_prev.week]),
+        request.GET.urlencode(),
+    )
+    context["url_next"] = "%s?%s" % (
+        reverse("timetable_by_week", args=[week_next.year, week_next.week]),
+        request.GET.urlencode(),
+    )
 
-    return render(request, 'chronos/tt_week.html', context)
+    return render(request, "chronos/tt_week.html", context)
 
 
 @login_required
@@ -93,7 +112,7 @@ def lessons_day(request: HttpRequest, when: Optional[str] = None) -> HttpRespons
     context = {}
 
     if when:
-        day = datetime.strptime(when, '%Y-%m-%d').date()
+        day = datetime.strptime(when, "%Y-%m-%d").date()
     else:
         day = date.today()
 
@@ -104,17 +123,21 @@ def lessons_day(request: HttpRequest, when: Optional[str] = None) -> HttpRespons
     lessons_table = LessonsTable(lesson_periods.all())
     RequestConfig(request).configure(lessons_table)
 
-    context['current_head'] = _('Lessons %s') % (day)
-    context['lessons_table'] = lessons_table
-    context['day'] = day
-    context['lesson_periods'] = lesson_periods
+    context["current_head"] = _("Lessons %s") % (day)
+    context["lessons_table"] = lessons_table
+    context["day"] = day
+    context["lesson_periods"] = lesson_periods
 
     day_prev = day - timedelta(days=1)
     day_next = day + timedelta(days=1)
-    context['url_prev'] = reverse('lessons_day_by_date', args=[day_prev.strftime('%Y-%m-%d')])
-    context['url_next'] = reverse('lessons_day_by_date', args=[day_next.strftime('%Y-%m-%d')])
+    context["url_prev"] = reverse(
+        "lessons_day_by_date", args=[day_prev.strftime("%Y-%m-%d")]
+    )
+    context["url_next"] = reverse(
+        "lessons_day_by_date", args=[day_next.strftime("%Y-%m-%d")]
+    )
 
-    return render(request, 'chronos/lessons_day.html', context)
+    return render(request, "chronos/lessons_day.html", context)
 
 
 @admin_required
@@ -125,26 +148,33 @@ def edit_substitution(request: HttpRequest, id_: int, week: int) -> HttpResponse
     wanted_week = lesson_period.lesson.get_calendar_week(week)
 
     lesson_substitution = LessonSubstitution.objects.filter(
-        week=wanted_week.week, lesson_period=lesson_period).first()
+        week=wanted_week.week, lesson_period=lesson_period
+    ).first()
     if lesson_substitution:
         edit_substitution_form = LessonSubstitutionForm(
-            request.POST or None, instance=lesson_substitution)
+            request.POST or None, instance=lesson_substitution
+        )
     else:
         edit_substitution_form = LessonSubstitutionForm(
-            request.POST or None, initial={'week': wanted_week.week, 'lesson_period': lesson_period})
+            request.POST or None,
+            initial={"week": wanted_week.week, "lesson_period": lesson_period},
+        )
 
-    context['substitution'] = lesson_substitution
+    context["substitution"] = lesson_substitution
 
-    if request.method == 'POST':
+    if request.method == "POST":
         if edit_substitution_form.is_valid():
             edit_substitution_form.save(commit=True)
 
-            messages.success(request, _('The substitution has been saved.'))
-            return redirect('lessons_day_by_date', when=wanted_week[lesson_period.period.weekday - 1].strftime('%Y-%m-%d'))
+            messages.success(request, _("The substitution has been saved."))
+            return redirect(
+                "lessons_day_by_date",
+                when=wanted_week[lesson_period.period.weekday - 1].strftime("%Y-%m-%d"),
+            )
 
-    context['edit_substitution_form'] = edit_substitution_form
+    context["edit_substitution_form"] = edit_substitution_form
 
-    return render(request, 'chronos/edit_substitution.html', context)
+    return render(request, "chronos/edit_substitution.html", context)
 
 
 @admin_required
@@ -158,11 +188,16 @@ def delete_substitution(request: HttpRequest, id_: int, week: int) -> HttpRespon
         week=wanted_week.week, lesson_period=lesson_period
     ).delete()
 
-    messages.success(request, _('The substitution has been deleted.'))
-    return redirect('lessons_day_by_date', when=wanted_week[lesson_period.period.weekday - 1].strftime('%Y-%m-%d'))
+    messages.success(request, _("The substitution has been deleted."))
+    return redirect(
+        "lessons_day_by_date",
+        when=wanted_week[lesson_period.period.weekday - 1].strftime("%Y-%m-%d"),
+    )
 
 
-def substitutions(request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None) -> HttpResponse:
+def substitutions(
+    request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None
+) -> HttpResponse:
     context = {}
 
     if week:
@@ -176,11 +211,15 @@ def substitutions(request: HttpRequest, year: Optional[int] = None, week: Option
     substitutions_table = SubstitutionsTable(substitutions)
     RequestConfig(request).configure(substitutions_table)
 
-    context['current_head'] = str(wanted_week)
-    context['substitutions_table'] = substitutions_table
+    context["current_head"] = str(wanted_week)
+    context["substitutions_table"] = substitutions_table
     week_prev = wanted_week - 1
     week_next = wanted_week + 1
-    context['url_prev'] = '%s' % (reverse('substitutions_by_week', args=[week_prev.year, week_prev.week]))
-    context['url_next'] = '%s' % (reverse('substitutions_by_week', args=[week_next.year, week_next.week]))
-
-    return render(request, 'chronos/substitutions.html', context)
+    context["url_prev"] = "%s" % (
+        reverse("substitutions_by_week", args=[week_prev.year, week_prev.week])
+    )
+    context["url_next"] = "%s" % (
+        reverse("substitutions_by_week", args=[week_next.year, week_next.week])
+    )
+
+    return render(request, "chronos/substitutions.html", context)