diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000000000000000000000000000000000000..e46c3310bf31324d76871fe8234d9656473e13bb
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,4 @@
+[flake8]
+max-line-length = 99
+ignore = E121,E123,E126,E203,E226,E24,E704,W503,N802
+
diff --git a/profile/admin.py b/profile/admin.py
index 909b824e8da36a26f49d9d33e7ba56dfa09f44cc..0a93c66103e1e3aec33629c013b9597d77cb5c86 100644
--- a/profile/admin.py
+++ b/profile/admin.py
@@ -27,8 +27,8 @@ from .models import Profile
 class ProfileInline(admin.StackedInline):
     model = Profile
     can_delete = False
-    verbose_name_plural = 'Profile'
-    fk_name = 'user'
+    verbose_name_plural = "Profile"
+    fk_name = "user"
 
 
 class ProfileUserAdmin(UserAdmin):
@@ -37,7 +37,9 @@ class ProfileUserAdmin(UserAdmin):
     def get_queryset(self, request):
         """Let common users only edit their own profile"""
         if not request.user.is_superuser:
-            return super(UserAdmin, self).get_queryset(request).filter(pk=request.user.id)
+            return (
+                super(UserAdmin, self).get_queryset(request).filter(pk=request.user.id)
+            )
 
         return super(UserAdmin, self).get_queryset(request)
 
@@ -45,7 +47,15 @@ class ProfileUserAdmin(UserAdmin):
         """Limit field access for common users"""
         if not request.user.is_superuser:
             return (
-            'username', 'is_staff', 'is_superuser', 'is_active', 'date_joined', 'last_login', 'groups', 'user_permissions')
+                "username",
+                "is_staff",
+                "is_superuser",
+                "is_active",
+                "date_joined",
+                "last_login",
+                "groups",
+                "user_permissions",
+            )
         return list()
 
     def get_inline_instances(self, request, obj=None):
diff --git a/profile/migrations/0001_initial.py b/profile/migrations/0001_initial.py
index e55dd0d75a6ea3c9e628c1a0add066056d091880..cf221f507e56f33406dcb118baed4df5d2d1e33a 100644
--- a/profile/migrations/0001_initial.py
+++ b/profile/migrations/0001_initial.py
@@ -18,28 +18,104 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='Profile',
+            name="Profile",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('biography', models.TextField(blank=True, null=True, verbose_name='Biography')),
-                ('website', models.URLField(blank=True, verbose_name='Website')),
-                ('googleplus_url', models.URLField(blank=True, verbose_name='Google+ URL')),
-                ('facebook_url', models.URLField(blank=True, verbose_name='Facebook URL')),
-                ('twitter_url', models.URLField(blank=True, verbose_name='Twitter URL')),
-                ('linkedin_url', models.URLField(blank=True, verbose_name='LinkedIn URL')),
-                ('youtube_url', models.URLField(blank=True, verbose_name='Youtube URL')),
-                ('dorftv_url', models.URLField(blank=True, verbose_name='DorfTV URL')),
-                ('cba_url', models.URLField(blank=True, verbose_name='CBA URL')),
-                ('cba_username', models.CharField(blank=True, max_length=60, verbose_name='CBA Username')),
-                ('cba_user_token', models.CharField(blank=True, max_length=255, verbose_name='CBA Token')),
-                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
-                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
-                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
-                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='user_images', verbose_name='Profile picture', width_field='width')),
-                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "biography",
+                    models.TextField(blank=True, null=True, verbose_name="Biography"),
+                ),
+                ("website", models.URLField(blank=True, verbose_name="Website")),
+                (
+                    "googleplus_url",
+                    models.URLField(blank=True, verbose_name="Google+ URL"),
+                ),
+                (
+                    "facebook_url",
+                    models.URLField(blank=True, verbose_name="Facebook URL"),
+                ),
+                (
+                    "twitter_url",
+                    models.URLField(blank=True, verbose_name="Twitter URL"),
+                ),
+                (
+                    "linkedin_url",
+                    models.URLField(blank=True, verbose_name="LinkedIn URL"),
+                ),
+                (
+                    "youtube_url",
+                    models.URLField(blank=True, verbose_name="Youtube URL"),
+                ),
+                ("dorftv_url", models.URLField(blank=True, verbose_name="DorfTV URL")),
+                ("cba_url", models.URLField(blank=True, verbose_name="CBA URL")),
+                (
+                    "cba_username",
+                    models.CharField(
+                        blank=True, max_length=60, verbose_name="CBA Username"
+                    ),
+                ),
+                (
+                    "cba_user_token",
+                    models.CharField(
+                        blank=True, max_length=255, verbose_name="CBA Token"
+                    ),
+                ),
+                (
+                    "ppoi",
+                    versatileimagefield.fields.PPOIField(
+                        default="0.5x0.5",
+                        editable=False,
+                        max_length=20,
+                        verbose_name="Image PPOI",
+                    ),
+                ),
+                (
+                    "height",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Height",
+                    ),
+                ),
+                (
+                    "width",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Width",
+                    ),
+                ),
+                (
+                    "image",
+                    versatileimagefield.fields.VersatileImageField(
+                        blank=True,
+                        height_field="height",
+                        null=True,
+                        upload_to="user_images",
+                        verbose_name="Profile picture",
+                        width_field="width",
+                    ),
+                ),
+                (
+                    "user",
+                    models.OneToOneField(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
             ],
             options={
-                'db_table': 'profile',
+                "db_table": "profile",
             },
         ),
     ]
diff --git a/profile/migrations/0001_squashed.py b/profile/migrations/0001_squashed.py
index e0e3632cfc0b65106bc182cc368695102da9a7e7..50f9e213819275b1cef01be96bd42094bfff8e99 100644
--- a/profile/migrations/0001_squashed.py
+++ b/profile/migrations/0001_squashed.py
@@ -7,7 +7,11 @@ import django.db.models.deletion
 
 class Migration(migrations.Migration):
 
-    replaces = [('profile', '0001_initial'), ('profile', '0002_auto_20171129_1828'), ('profile', '0003_auto_20171213_1737')]
+    replaces = [
+        ("profile", "0001_initial"),
+        ("profile", "0002_auto_20171129_1828"),
+        ("profile", "0003_auto_20171213_1737"),
+    ]
 
     initial = True
 
@@ -17,15 +21,49 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='Profile',
+            name="Profile",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('cba_username', models.CharField(blank=True, help_text='Your username in CBA. This is necessary for uploading files to your account.', max_length=60, verbose_name='CBA Username')),
-                ('cba_user_token', models.CharField(blank=True, help_text='The CBA upload token for your account. This is NOT your password which you use to log into CBA!', max_length=255, verbose_name='CBA Token')),
-                ('user', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "cba_username",
+                    models.CharField(
+                        blank=True,
+                        help_text="Your username in CBA. This is necessary for uploading files to"
+                                  " your account.",
+                        max_length=60,
+                        verbose_name="CBA Username",
+                    ),
+                ),
+                (
+                    "cba_user_token",
+                    models.CharField(
+                        blank=True,
+                        help_text="The CBA upload token for your account. This is NOT your"
+                                  " password which you use to log into CBA!",
+                        max_length=255,
+                        verbose_name="CBA Token",
+                    ),
+                ),
+                (
+                    "user",
+                    models.OneToOneField(
+                        editable=False,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="profile",
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
             ],
             options={
-                'db_table': 'profile',
+                "db_table": "profile",
             },
         ),
     ]
diff --git a/profile/migrations/0002_auto_20171129_1828.py b/profile/migrations/0002_auto_20171129_1828.py
index 77147dda7df704cf6c9854eb4473f0198e736b4a..1f30c9a009497a5f0278403137b675c57af3cccc 100644
--- a/profile/migrations/0002_auto_20171129_1828.py
+++ b/profile/migrations/0002_auto_20171129_1828.py
@@ -11,73 +11,135 @@ import versatileimagefield.fields
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('profile', '0001_initial'),
+        ("profile", "0001_initial"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='profile',
-            name='biography',
-            field=models.TextField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography'),
+            model_name="profile",
+            name="biography",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe yourself and your fields of interest in a few sentences.",
+                null=True,
+                verbose_name="Biography",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='cba_url',
-            field=models.URLField(blank=True, help_text='URL to your CBA profile.', verbose_name='CBA URL'),
+            model_name="profile",
+            name="cba_url",
+            field=models.URLField(
+                blank=True, help_text="URL to your CBA profile.", verbose_name="CBA URL"
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='cba_user_token',
-            field=models.CharField(blank=True, help_text='The CBA upload token for your account. This is NOT your password which you use to log into CBA!', max_length=255, verbose_name='CBA Token'),
+            model_name="profile",
+            name="cba_user_token",
+            field=models.CharField(
+                blank=True,
+                help_text="The CBA upload token for your account. This is NOT your password which"
+                          " you use to log into CBA!",
+                max_length=255,
+                verbose_name="CBA Token",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='cba_username',
-            field=models.CharField(blank=True, help_text='Your username in CBA. This is necessary for uploading files to your account.', max_length=60, verbose_name='CBA Username'),
+            model_name="profile",
+            name="cba_username",
+            field=models.CharField(
+                blank=True,
+                help_text="Your username in CBA. This is necessary for uploading files to your"
+                          " account.",
+                max_length=60,
+                verbose_name="CBA Username",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='dorftv_url',
-            field=models.URLField(blank=True, help_text='URL to your dorfTV channel.', verbose_name='DorfTV URL'),
+            model_name="profile",
+            name="dorftv_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your dorfTV channel.",
+                verbose_name="DorfTV URL",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='facebook_url',
-            field=models.URLField(blank=True, help_text='URL to your Facebook profile.', verbose_name='Facebook URL'),
+            model_name="profile",
+            name="facebook_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Facebook profile.",
+                verbose_name="Facebook URL",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='googleplus_url',
-            field=models.URLField(blank=True, help_text='URL to your Google+ profile.', verbose_name='Google+ URL'),
+            model_name="profile",
+            name="googleplus_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Google+ profile.",
+                verbose_name="Google+ URL",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='user_images', verbose_name='Profile picture', width_field='width'),
+            model_name="profile",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                help_text="Upload a picture of yourself. Images are automatically cropped around"
+                          " the 'Primary Point of Interest'. Click in the image to change it and"
+                          " press Save.",
+                null=True,
+                upload_to="user_images",
+                verbose_name="Profile picture",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='linkedin_url',
-            field=models.URLField(blank=True, help_text='URL to your LinkedIn profile.', verbose_name='LinkedIn URL'),
+            model_name="profile",
+            name="linkedin_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your LinkedIn profile.",
+                verbose_name="LinkedIn URL",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='twitter_url',
-            field=models.URLField(blank=True, help_text='URL to your Twitter profile.', verbose_name='Twitter URL'),
+            model_name="profile",
+            name="twitter_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Twitter profile.",
+                verbose_name="Twitter URL",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='user',
-            field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL),
+            model_name="profile",
+            name="user",
+            field=models.OneToOneField(
+                editable=False,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="profile",
+                to=settings.AUTH_USER_MODEL,
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='website',
-            field=models.URLField(blank=True, help_text='URL to your personal website.', verbose_name='Website'),
+            model_name="profile",
+            name="website",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your personal website.",
+                verbose_name="Website",
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='youtube_url',
-            field=models.URLField(blank=True, help_text='URL to your Youtube channel.', verbose_name='Youtube URL'),
+            model_name="profile",
+            name="youtube_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Youtube channel.",
+                verbose_name="Youtube URL",
+            ),
         ),
     ]
diff --git a/profile/migrations/0002_auto_20220117_1721.py b/profile/migrations/0002_auto_20220117_1721.py
index d4969d4ae45de9f045af5934a54640b9f7e9d28b..e209efdea852e921a271540fe56c4e686a9c7f75 100644
--- a/profile/migrations/0002_auto_20220117_1721.py
+++ b/profile/migrations/0002_auto_20220117_1721.py
@@ -6,18 +6,22 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('profile', '0001_squashed'),
+        ("profile", "0001_squashed"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='profile',
-            name='cba_user_token',
-            field=models.CharField(blank=True, max_length=255, verbose_name='CBA Token'),
+            model_name="profile",
+            name="cba_user_token",
+            field=models.CharField(
+                blank=True, max_length=255, verbose_name="CBA Token"
+            ),
         ),
         migrations.AlterField(
-            model_name='profile',
-            name='cba_username',
-            field=models.CharField(blank=True, max_length=60, verbose_name='CBA Username'),
+            model_name="profile",
+            name="cba_username",
+            field=models.CharField(
+                blank=True, max_length=60, verbose_name="CBA Username"
+            ),
         ),
     ]
diff --git a/profile/migrations/0003_auto_20171213_1737.py b/profile/migrations/0003_auto_20171213_1737.py
index 1d4de59c5312a4407eff36f2a9459bd550e2d008..8a4b11031e742c40aec3dd314efbf7e8018c19c0 100644
--- a/profile/migrations/0003_auto_20171213_1737.py
+++ b/profile/migrations/0003_auto_20171213_1737.py
@@ -8,60 +8,60 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('profile', '0002_auto_20171129_1828'),
+        ("profile", "0002_auto_20171129_1828"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='profile',
-            name='biography',
+            model_name="profile",
+            name="biography",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='cba_url',
+            model_name="profile",
+            name="cba_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='dorftv_url',
+            model_name="profile",
+            name="dorftv_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='facebook_url',
+            model_name="profile",
+            name="facebook_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='googleplus_url',
+            model_name="profile",
+            name="googleplus_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='height',
+            model_name="profile",
+            name="height",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='image',
+            model_name="profile",
+            name="image",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='linkedin_url',
+            model_name="profile",
+            name="linkedin_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='ppoi',
+            model_name="profile",
+            name="ppoi",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='twitter_url',
+            model_name="profile",
+            name="twitter_url",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='website',
+            model_name="profile",
+            name="website",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='width',
+            model_name="profile",
+            name="width",
         ),
         migrations.RemoveField(
-            model_name='profile',
-            name='youtube_url',
+            model_name="profile",
+            name="youtube_url",
         ),
     ]
diff --git a/profile/models.py b/profile/models.py
index cc3316110b7e35293a8f211e4997213c6bddd769..743639222894e49eaadaf7539e780d9497a3ade0 100644
--- a/profile/models.py
+++ b/profile/models.py
@@ -23,7 +23,9 @@ from django.utils.translation import gettext_lazy as _
 
 
 class Profile(models.Model):
-    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', editable=False)
+    user = models.OneToOneField(
+        User, on_delete=models.CASCADE, related_name="profile", editable=False
+    )
     cba_username = models.CharField(_("CBA Username"), blank=True, max_length=60)
     cba_user_token = models.CharField(_("CBA Token"), blank=True, max_length=255)
 
@@ -31,7 +33,7 @@ class Profile(models.Model):
         return self.user.username
 
     class Meta:
-        db_table = 'profile'
+        db_table = "profile"
 
     def save(self, *args, **kwargs):
         super(Profile, self).save(*args, **kwargs)
diff --git a/profile/serializers.py b/profile/serializers.py
index 377894a8b9f88f3d0213a79e65917f512eb4cc2e..dd06250e6038b7395f4e5fed0d32ce383e203d44 100644
--- a/profile/serializers.py
+++ b/profile/serializers.py
@@ -25,4 +25,4 @@ from profile.models import Profile
 class ProfileSerializer(serializers.ModelSerializer):
     class Meta:
         model = Profile
-        fields = '__all__'
+        fields = "__all__"
diff --git a/program/management/commands/addnote.py b/program/management/commands/addnote.py
index 7b8aff6ada714fc526a156d175fc495e9d1aafa6..d78ec535c5fbb24a27f499089201d44bb300dc8b 100644
--- a/program/management/commands/addnote.py
+++ b/program/management/commands/addnote.py
@@ -8,8 +8,8 @@ from program.utils import parse_date
 
 
 class Command(BaseCommand):
-    help = 'adds a note to a timeslot'
-    args = '<show_id> <start_date> <status> [index]'
+    help = "adds a note to a timeslot"
+    args = "<show_id> <start_date> <status> [index]"
 
     def handle(self, *args, **options):
         if len(args) == 3:
@@ -22,7 +22,9 @@ class Command(BaseCommand):
             status = args[2]
             index = args[3]
         else:
-            raise CommandError('you must provide the show_id, start_date, status [index]')
+            raise CommandError(
+                "you must provide the show_id, start_date, status [index]"
+            )
 
         try:
             show = Show.objects.get(id=show_id)
@@ -37,16 +39,20 @@ class Command(BaseCommand):
             year, month, day = start.year, start.month, start.day
 
         try:
-            timeslot = TimeSlot.objects.get(show=show, start__year=year, start__month=month, start__day=day)
+            timeslot = TimeSlot.objects.get(
+                show=show, start__year=year, start__month=month, start__day=day
+            )
         except TimeSlot.DoesNotExist as dne:
             raise CommandError(dne)
         except TimeSlot.MultipleObjectsReturned:
             if not index:
-                raise CommandError('you must provide the show_id, start_date, status index')
+                raise CommandError(
+                    "you must provide the show_id, start_date, status index"
+                )
             try:
-                timeslot = \
-                    TimeSlot.objects.filter(show=show, start__year=year, start__month=month, start__day=day).order_by(
-                        'start')[int(index)]
+                timeslot = TimeSlot.objects.filter(
+                    show=show, start__year=year, start__month=month, start__day=day
+                ).order_by("start")[int(index)]
             except IndexError as ie:
                 raise CommandError(ie)
 
@@ -56,7 +62,9 @@ class Command(BaseCommand):
         except Exception as e:
             raise CommandError(e)
 
-        note = Note(timeslot=timeslot, title=title, content=''.join(lines), status=status)
+        note = Note(
+            timeslot=timeslot, title=title, content="".join(lines), status=status
+        )
 
         try:
             note.validate_unique()
@@ -64,4 +72,6 @@ class Command(BaseCommand):
             raise CommandError(ve.messages[0])
         else:
             note.save()
-            self.stdout.write(self.style.SUCCESS, f'added note "{title}" to "{timeslot}"')
+            self.stdout.write(
+                self.style.SUCCESS, f'added note "{title}" to "{timeslot}"'
+            )
diff --git a/program/management/commands/create_oidc_client.py b/program/management/commands/create_oidc_client.py
index dfb96241bc488f29b424af71bb8d0b624a9a2c5d..46d3d2b19aa5517ba67a167ed26afc99fc33eba1 100644
--- a/program/management/commands/create_oidc_client.py
+++ b/program/management/commands/create_oidc_client.py
@@ -7,42 +7,100 @@ from oidc_provider.models import Client, ResponseType
 
 
 class Command(BaseCommand):
-    help = 'Sets up an OIDC client / relaying party. For details check out the' + \
-           'section on Relying Parties at https://django-oidc-provider.readthedocs.io'
+    help = (
+        "Sets up an OIDC client / relaying party. For details check out the"
+        + "section on Relying Parties at https://django-oidc-provider.readthedocs.io"
+    )
 
     def add_arguments(self, parser):
-        parser.add_argument('name', type=str,
-                            help='A label that you associate with this client')
-        parser.add_argument('client_type', type=str, choices=['public', 'confidential'],
-                            help='The type of client can be either public or confidential')
-        parser.add_argument('--client-id', type=int, dest='client_id', action='store', help='The client ID ')
+        parser.add_argument(
+            "name", type=str, help="A label that you associate with this client"
+        )
+        parser.add_argument(
+            "client_type",
+            type=str,
+            choices=["public", "confidential"],
+            help="The type of client can be either public or confidential",
+        )
+        parser.add_argument(
+            "--client-id",
+            type=int,
+            dest="client_id",
+            action="store",
+            help="The client ID ",
+        )
         parser.set_defaults(client_id=None)
-        parser.add_argument('--client-secret', type=str, dest='client_secret', action='store', help='The client secret')
+        parser.add_argument(
+            "--client-secret",
+            type=str,
+            dest="client_secret",
+            action="store",
+            help="The client secret",
+        )
         parser.set_defaults(client_secret=None)
-        parser.add_argument('--no-require-consent', dest='require_consent', action='store_false',
-                            help='By default user consent is required. Use this to skip user consent.')
-        parser.add_argument('--no-reuse-consent', dest='reuse_consent', action='store_false',
-                            help='By default user consent will be reused. Use this if the user should provide consent on every login.')
+        parser.add_argument(
+            "--no-require-consent",
+            dest="require_consent",
+            action="store_false",
+            help="By default user consent is required. Use this to skip user consent.",
+        )
+        parser.add_argument(
+            "--no-reuse-consent",
+            dest="reuse_consent",
+            action="store_false",
+            help="By default user consent will be reused. Use this if the user should provide"
+                 " consent on every login.",
+        )
         parser.set_defaults(require_consent=True, reuse_consent=True)
-        parser.add_argument('-u', '--redirect-uri', type=str, action='append',
-                            help='Redirect URI after successful authentication. Can be used more than once.')
-        parser.add_argument('-p', '--post-logout-redirect', type=str, action='append',
-                            help='Post logout redirect URI. Can be used more than once.')
-        parser.add_argument('-s', '--scope', type=str, action='append',
-                            help='Authorized scope values for this client. Can be used more than once.')
-        parser.add_argument('-r', dest='response_types', action='append',
-                            choices=['code', 'id_token', 'id_token token', 'code token', 'code id_token',
-                                     'code id_token token'],
-                            help='The type of response the client will get.')
-        parser.add_argument('-i', '--id-only', dest='id_only', action='store_true',
-                            help='Do not print anything else then the ID of the newly created client ' + \
-                                 '(and the client secret in case of confidential clients).')
+        parser.add_argument(
+            "-u",
+            "--redirect-uri",
+            type=str,
+            action="append",
+            help="Redirect URI after successful authentication. Can be used more than once.",
+        )
+        parser.add_argument(
+            "-p",
+            "--post-logout-redirect",
+            type=str,
+            action="append",
+            help="Post logout redirect URI. Can be used more than once.",
+        )
+        parser.add_argument(
+            "-s",
+            "--scope",
+            type=str,
+            action="append",
+            help="Authorized scope values for this client. Can be used more than once.",
+        )
+        parser.add_argument(
+            "-r",
+            dest="response_types",
+            action="append",
+            choices=[
+                "code",
+                "id_token",
+                "id_token token",
+                "code token",
+                "code id_token",
+                "code id_token token",
+            ],
+            help="The type of response the client will get.",
+        )
+        parser.add_argument(
+            "-i",
+            "--id-only",
+            dest="id_only",
+            action="store_true",
+            help="Do not print anything else then the ID of the newly created client "
+            + "(and the client secret in case of confidential clients).",
+        )
         parser.set_defaults(id_only=False)
 
     def handle(self, *args, **options):
-        if options['client_id'] and options['client_secret']:
-            client_id = options['client_id']
-            client_secret = options['client_secret']
+        if options["client_id"] and options["client_secret"]:
+            client_id = options["client_id"]
+            client_secret = options["client_secret"]
         else:
             # generate a new client ID and secret
             client_id = False
@@ -51,9 +109,11 @@ class Command(BaseCommand):
                 client_id = random.randint(100000, 999999)
                 counter += 1
                 if counter > 10000:
-                    raise CommandError('Could not find a free client_id. Already' +
-                                       ' tried 10000 times. There seems to be something seriously' +
-                                       ' wrong with your setup. Please inspect manually.')
+                    raise CommandError(
+                        "Could not find a free client_id. Already"
+                        + " tried 10000 times. There seems to be something seriously"
+                        + " wrong with your setup. Please inspect manually."
+                    )
                 try:
                     Client.objects.get(client_id=client_id)
                 except Client.DoesNotExist:
@@ -61,17 +121,20 @@ class Command(BaseCommand):
                 else:
                     client_id = False
 
-            client_secret = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(32))
+            client_secret = "".join(
+                random.SystemRandom().choice(string.ascii_letters + string.digits)
+                for _ in range(32)
+            )
 
-        show_results = options['client_id'] is None and options['client_secret'] is None
+        show_results = options["client_id"] is None and options["client_secret"] is None
 
         # initialize lists if no option was provided
-        if options['redirect_uri'] is None:
-            options['redirect_uri'] = []
-        if options['post_logout_redirect'] is None:
-            options['post_logout_redirect'] = []
-        if options['scope'] is None:
-            options['scope'] = []
+        if options["redirect_uri"] is None:
+            options["redirect_uri"] = []
+        if options["post_logout_redirect"] is None:
+            options["post_logout_redirect"] = []
+        if options["scope"] is None:
+            options["scope"] = []
 
         if not options["id_only"] and show_results:
             self.stdout.write(f'Creating client with name {options["name"]}')
@@ -79,34 +142,43 @@ class Command(BaseCommand):
             c = Client(
                 client_id=client_id,
                 client_secret=client_secret,
-                name=options['name'], client_type=options['client_type'],
-                redirect_uris=options['redirect_uri'],
-                require_consent=options['require_consent'],
-                reuse_consent=options['reuse_consent'],
-                post_logout_redirect_uris=options['post_logout_redirect'],
-                scope=options['scope'],
+                name=options["name"],
+                client_type=options["client_type"],
+                redirect_uris=options["redirect_uri"],
+                require_consent=options["require_consent"],
+                reuse_consent=options["reuse_consent"],
+                post_logout_redirect_uris=options["post_logout_redirect"],
+                scope=options["scope"],
             )
             c.save()
-        except:
-            raise CommandError('Could not create an OpenID connect client' +
-                               f' due to the following error: {sys.exc_info()}')
+        except Exception:
+            raise CommandError(
+                "Could not create an OpenID connect client"
+                + f" due to the following error: {sys.exc_info()}"
+            )
 
-        if options['response_types']:
+        if options["response_types"]:
             try:
-                for r_value in options['response_types']:
+                for r_value in options["response_types"]:
                     r = ResponseType.objects.get(value=r_value)
                     c.response_types.add(r)
-            except:
-                raise CommandError('Client was stored, but could not set response_types' +
-                                   f' due to the following error: {sys.exc_info()}')
+            except Exception:
+                raise CommandError(
+                    "Client was stored, but could not set response_types"
+                    + f" due to the following error: {sys.exc_info()}"
+                )
 
         if show_results:
             if options["id_only"]:
-                if options['client_type'] == 'confidential':
-                    self.stdout.write(f'{c.client_id} {c.client_secret}')
+                if options["client_type"] == "confidential":
+                    self.stdout.write(f"{c.client_id} {c.client_secret}")
                 else:
-                    self.stdout.write(f'{c.client_id}')
+                    self.stdout.write(f"{c.client_id}")
             else:
-                self.stdout.write(f'Successfully created new OIDC client, with ID: {c.client_id}')
-                if options['client_type'] == 'confidential':
-                    self.stdout.write(f'The secret for this confidential client is: {c.client_secret}')
+                self.stdout.write(
+                    f"Successfully created new OIDC client, with ID: {c.client_id}"
+                )
+                if options["client_type"] == "confidential":
+                    self.stdout.write(
+                        f"The secret for this confidential client is: {c.client_secret}"
+                    )
diff --git a/program/management/commands/createuser.py b/program/management/commands/createuser.py
index 25985c0171ea8e1302053d7c609fd317e71cf20c..3e816ccd90e599166bc767baed7240f3c43f19cb 100644
--- a/program/management/commands/createuser.py
+++ b/program/management/commands/createuser.py
@@ -3,15 +3,27 @@ from django.core.management.base import BaseCommand, CommandError
 
 
 class Command(BaseCommand):
-    help = 'creates an user'
+    help = "creates an user"
 
     def add_arguments(self, parser):
-        parser.add_argument('--username', action='store', help='Specifies the username.', required=True, type=str)
-        parser.add_argument('--email', action='store', help='Specifies the email address.', required=True, type=str)
+        parser.add_argument(
+            "--username",
+            action="store",
+            help="Specifies the username.",
+            required=True,
+            type=str,
+        )
+        parser.add_argument(
+            "--email",
+            action="store",
+            help="Specifies the email address.",
+            required=True,
+            type=str,
+        )
 
     def handle(self, *args, **options):
-        username = options.get('username', None)
-        email = options.get('email', None)
+        username = options.get("username", None)
+        email = options.get("email", None)
 
         if not username or not email:
             raise CommandError("You must use --username and --email.")
@@ -19,6 +31,8 @@ class Command(BaseCommand):
             User.objects.get(username=username)
         except User.DoesNotExist:
             User.objects.create_user(username=username, email=email)
-            self.stdout.write(self.style.SUCCESS('user created successfully.'))
+            self.stdout.write(self.style.SUCCESS("user created successfully."))
         else:
-            self.stdout.write(self.style.NOTICE('User already exists, no need to create.'))
+            self.stdout.write(
+                self.style.NOTICE("User already exists, no need to create.")
+            )
diff --git a/program/management/commands/deleteuser.py b/program/management/commands/deleteuser.py
index 97c44641e5a9804b237d78ba58b4ee4658762a06..4cbbe833dbfd9429f60fbdcbedcdbc6b41d8480d 100644
--- a/program/management/commands/deleteuser.py
+++ b/program/management/commands/deleteuser.py
@@ -3,19 +3,25 @@ from django.core.management.base import BaseCommand, CommandError
 
 
 class Command(BaseCommand):
-    help = 'deletes an user'
+    help = "deletes an user"
 
     def add_arguments(self, parser):
-        parser.add_argument('--username', action='store', help='Specifies the username.', required=True, type=str),
+        parser.add_argument(
+            "--username",
+            action="store",
+            help="Specifies the username.",
+            required=True,
+            type=str,
+        ),
 
     def handle(self, *args, **options):
-        username = options.get('username', None)
+        username = options.get("username", None)
 
         if not username:
             raise CommandError("You must use --username.")
         try:
             User.objects.get(username=username).delete()
         except User.DoesNotExist:
-            raise 'user does not exist.'
+            raise "user does not exist."
         else:
-            self.stdout.write(self.style.SUCCESS('user deleted successfully.'))
+            self.stdout.write(self.style.SUCCESS("user deleted successfully."))
diff --git a/program/management/commands/export_showlog.py b/program/management/commands/export_showlog.py
index e5c86a83d10dacc954f2ca00b042b94c24586639..0cf4ca0d53d36891c680d651782681b85f568b1b 100644
--- a/program/management/commands/export_showlog.py
+++ b/program/management/commands/export_showlog.py
@@ -8,11 +8,11 @@ from program.models import TimeSlot
 
 
 class Command(BaseCommand):
-    help = 'export playlog for one year'
-    args = '<year>'
+    help = "export playlog for one year"
+    args = "<year>"
 
     def handle(self, *args, **options):
-        UTF8Writer = codecs.getwriter('utf8')
+        UTF8Writer = codecs.getwriter("utf8")
         sys.stdout = UTF8Writer(sys.stdout)
 
         if len(args) == 1:
@@ -21,23 +21,32 @@ class Command(BaseCommand):
             except ValueError:
                 raise CommandError("'%s' is not a valid year" % args[0])
         else:
-            raise CommandError('you must provide the year')
+            raise CommandError("you must provide the year")
 
         self.stdout.write(self.style.NOTICE, f"# Radio Helsinki Sendungslog {year}")
 
         start = datetime(year, 1, 1, 0, 0)
-        end = datetime(year+1, 1, 1, 0, 0)
+        end = datetime(year + 1, 1, 1, 0, 0)
 
         currentDate = None
-        for ts in TimeSlot.objects.filter(end__gt=start, start__lt=end).select_related('schedule').select_related('show'):
+        for ts in (
+            TimeSlot.objects.filter(end__gt=start, start__lt=end)
+            .select_related("schedule")
+            .select_related("show")
+        ):
             if currentDate is None or currentDate < ts.start.date():
                 if currentDate:
-                    self.stdout.write('\n')
+                    self.stdout.write("\n")
                 currentDate = ts.start.date()
-                self.stdout.write(self.style.NOTICE, currentDate.strftime("## %a %d.%m.%Y:\n"))
+                self.stdout.write(
+                    self.style.NOTICE, currentDate.strftime("## %a %d.%m.%Y:\n")
+                )
 
             title = ts.show.name
             if ts.schedule.is_repetition:
                 title += " (WH)"
 
-            self.stdout.write(self.style.NOTICE, f' * **{ts.start.strftime("%H:%M:%S")} - {ts.end.strftime("%H:%M:%S")}**: {title}')
+            self.stdout.write(
+                self.style.NOTICE,
+                f' * **{ts.start.strftime("%H:%M:%S")} - {ts.end.strftime("%H:%M:%S")}**: {title}',
+            )
diff --git a/program/management/commands/remove_automation_id.py b/program/management/commands/remove_automation_id.py
index 75da30c56bc348ff05b82edf0199b439bec25ed4..6045ff23aa433ab5c3e45a62d4104e6fef1cc0d4 100644
--- a/program/management/commands/remove_automation_id.py
+++ b/program/management/commands/remove_automation_id.py
@@ -4,13 +4,13 @@ from program.models import Schedule
 
 
 class Command(BaseCommand):
-    help = 'removes the automation_id from the program slots'
-    args = '<automation_id>'
+    help = "removes the automation_id from the program slots"
+    args = "<automation_id>"
 
     def handle(self, *args, **options):
         if len(args) == 1:
             automation_id = args[0]
         else:
-            raise CommandError('you must provide the automation_id')
+            raise CommandError("you must provide the automation_id")
 
-        Schedule.objects.filter(automation_id=automation_id).update(automation_id=None)
\ No newline at end of file
+        Schedule.objects.filter(automation_id=automation_id).update(automation_id=None)
diff --git a/program/migrations/0001_initial.py b/program/migrations/0001_initial.py
index ebbe4293995e8a45754043208a42a84e7dd138d3..7a93e423d159d381688c743fd953702a889ef14d 100644
--- a/program/migrations/0001_initial.py
+++ b/program/migrations/0001_initial.py
@@ -13,215 +13,602 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='BroadcastFormat',
+            name="BroadcastFormat",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('format', models.CharField(max_length=32, verbose_name='Format')),
-                ('slug', models.SlugField(unique=True, max_length=32, verbose_name='Slug')),
-                ('color', models.CharField(default=b'#ffffff', max_length=7, verbose_name='Color')),
-                ('text_color', models.CharField(default=b'#000000', max_length=7, verbose_name='Text color')),
-                ('enabled', models.BooleanField(default=True, verbose_name='Enabled')),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("format", models.CharField(max_length=32, verbose_name="Format")),
+                (
+                    "slug",
+                    models.SlugField(unique=True, max_length=32, verbose_name="Slug"),
+                ),
+                (
+                    "color",
+                    models.CharField(
+                        default=b"#ffffff", max_length=7, verbose_name="Color"
+                    ),
+                ),
+                (
+                    "text_color",
+                    models.CharField(
+                        default=b"#000000", max_length=7, verbose_name="Text color"
+                    ),
+                ),
+                ("enabled", models.BooleanField(default=True, verbose_name="Enabled")),
             ],
             options={
-                'ordering': ('format',),
-                'verbose_name': 'Broadcast format',
-                'verbose_name_plural': 'Broadcast formats',
+                "ordering": ("format",),
+                "verbose_name": "Broadcast format",
+                "verbose_name_plural": "Broadcast formats",
             },
         ),
         migrations.CreateModel(
-            name='Host',
+            name="Host",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(max_length=128, verbose_name='Name')),
-                ('email', models.EmailField(max_length=254, verbose_name='E-Mail', blank=True)),
-                ('website', models.URLField(verbose_name='Website', blank=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("name", models.CharField(max_length=128, verbose_name="Name")),
+                (
+                    "email",
+                    models.EmailField(
+                        max_length=254, verbose_name="E-Mail", blank=True
+                    ),
+                ),
+                ("website", models.URLField(verbose_name="Website", blank=True)),
             ],
             options={
-                'ordering': ('name',),
-                'verbose_name': 'Host',
-                'verbose_name_plural': 'Hosts',
+                "ordering": ("name",),
+                "verbose_name": "Host",
+                "verbose_name_plural": "Hosts",
             },
         ),
         migrations.CreateModel(
-            name='MusicFocus',
+            name="MusicFocus",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('focus', models.CharField(max_length=32, verbose_name='Focus')),
-                ('abbrev', models.CharField(unique=True, max_length=4, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(unique=True, max_length=32, verbose_name='Slug')),
-                ('button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image', blank=True)),
-                ('button_hover', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image (hover)', blank=True)),
-                ('big_button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Big button image', blank=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("focus", models.CharField(max_length=32, verbose_name="Focus")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        unique=True, max_length=4, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(unique=True, max_length=32, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image (hover)",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Big button image",
+                        blank=True,
+                    ),
+                ),
             ],
             options={
-                'ordering': ('focus',),
-                'verbose_name': 'Music focus',
-                'verbose_name_plural': 'Music focus',
+                "ordering": ("focus",),
+                "verbose_name": "Music focus",
+                "verbose_name_plural": "Music focus",
             },
         ),
         migrations.CreateModel(
-            name='Note',
+            name="Note",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('title', models.CharField(max_length=128, verbose_name='Title')),
-                ('content', models.TextField(verbose_name='Content')),
-                ('status', models.IntegerField(default=1, verbose_name='Status', choices=[(0, 'Cancellation'), (1, 'Recommendation'), (2, 'Repetition')])),
-                ('cba_entry_id', models.IntegerField(null=True, verbose_name='CBA entry ID', blank=True)),
-                ('start', models.DateTimeField(editable=False)),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(auto_now=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("title", models.CharField(max_length=128, verbose_name="Title")),
+                ("content", models.TextField(verbose_name="Content")),
+                (
+                    "status",
+                    models.IntegerField(
+                        default=1,
+                        verbose_name="Status",
+                        choices=[
+                            (0, "Cancellation"),
+                            (1, "Recommendation"),
+                            (2, "Repetition"),
+                        ],
+                    ),
+                ),
+                (
+                    "cba_entry_id",
+                    models.IntegerField(
+                        null=True, verbose_name="CBA entry ID", blank=True
+                    ),
+                ),
+                ("start", models.DateTimeField(editable=False)),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("last_updated", models.DateTimeField(auto_now=True)),
             ],
             options={
-                'ordering': ('timeslot',),
-                'verbose_name': 'Note',
-                'verbose_name_plural': 'Notes',
+                "ordering": ("timeslot",),
+                "verbose_name": "Note",
+                "verbose_name_plural": "Notes",
             },
         ),
         migrations.CreateModel(
-            name='ProgramSlot',
+            name="ProgramSlot",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('byweekday', models.IntegerField(verbose_name='Weekday', choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')])),
-                ('dstart', models.DateField(verbose_name='First date')),
-                ('tstart', models.TimeField(verbose_name='Start time')),
-                ('tend', models.TimeField(verbose_name='End time')),
-                ('until', models.DateField(verbose_name='Last date')),
-                ('is_repetition', models.BooleanField(default=False, verbose_name='Is repetition')),
-                ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID', choices=[])),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(auto_now=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                (
+                    "byweekday",
+                    models.IntegerField(
+                        verbose_name="Weekday",
+                        choices=[
+                            (0, "Monday"),
+                            (1, "Tuesday"),
+                            (2, "Wednesday"),
+                            (3, "Thursday"),
+                            (4, "Friday"),
+                            (5, "Saturday"),
+                            (6, "Sunday"),
+                        ],
+                    ),
+                ),
+                ("dstart", models.DateField(verbose_name="First date")),
+                ("tstart", models.TimeField(verbose_name="Start time")),
+                ("tend", models.TimeField(verbose_name="End time")),
+                ("until", models.DateField(verbose_name="Last date")),
+                (
+                    "is_repetition",
+                    models.BooleanField(default=False, verbose_name="Is repetition"),
+                ),
+                (
+                    "automation_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Automation ID", choices=[]
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("last_updated", models.DateTimeField(auto_now=True)),
             ],
             options={
-                'ordering': ('dstart', 'tstart'),
-                'verbose_name': 'Program slot',
-                'verbose_name_plural': 'Program slots',
+                "ordering": ("dstart", "tstart"),
+                "verbose_name": "Program slot",
+                "verbose_name_plural": "Program slots",
             },
         ),
         migrations.CreateModel(
-            name='RRule',
+            name="RRule",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(unique=True, max_length=32, verbose_name='Name')),
-                ('freq', models.IntegerField(verbose_name='Frequency', choices=[(1, 'Monthly'), (2, 'Weekly'), (3, 'Daily')])),
-                ('interval', models.IntegerField(default=1, verbose_name='Interval')),
-                ('bysetpos', models.IntegerField(blank=True, null=True, verbose_name='Set position', choices=[(1, 'First'), (2, 'Second'), (3, 'Third'), (4, 'Fourth'), (5, 'Fifth'), (-1, 'Last')])),
-                ('count', models.IntegerField(null=True, verbose_name='Count', blank=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(unique=True, max_length=32, verbose_name="Name"),
+                ),
+                (
+                    "freq",
+                    models.IntegerField(
+                        verbose_name="Frequency",
+                        choices=[(1, "Monthly"), (2, "Weekly"), (3, "Daily")],
+                    ),
+                ),
+                ("interval", models.IntegerField(default=1, verbose_name="Interval")),
+                (
+                    "bysetpos",
+                    models.IntegerField(
+                        blank=True,
+                        null=True,
+                        verbose_name="Set position",
+                        choices=[
+                            (1, "First"),
+                            (2, "Second"),
+                            (3, "Third"),
+                            (4, "Fourth"),
+                            (5, "Fifth"),
+                            (-1, "Last"),
+                        ],
+                    ),
+                ),
+                (
+                    "count",
+                    models.IntegerField(null=True, verbose_name="Count", blank=True),
+                ),
             ],
             options={
-                'ordering': ('-freq', 'interval', 'bysetpos'),
-                'verbose_name': 'Recurrence rule',
-                'verbose_name_plural': 'Recurrence rules',
+                "ordering": ("-freq", "interval", "bysetpos"),
+                "verbose_name": "Recurrence rule",
+                "verbose_name_plural": "Recurrence rules",
             },
         ),
         migrations.CreateModel(
-            name='Show',
+            name="Show",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(max_length=255, verbose_name='Name')),
-                ('slug', models.CharField(unique=True, max_length=255, verbose_name='Slug')),
-                ('image', models.ImageField(upload_to=b'show_images', null=True, verbose_name='Image', blank=True)),
-                ('image_enabled', models.BooleanField(default=True, verbose_name='show Image')),
-                ('short_description', models.CharField(max_length=64, verbose_name='Short description')),
-                ('description', models.TextField(null=True, verbose_name='Description', blank=True)),
-                ('email', models.EmailField(max_length=254, null=True, verbose_name='E-Mail', blank=True)),
-                ('website', models.URLField(null=True, verbose_name='Website', blank=True)),
-                ('cba_series_id', models.IntegerField(null=True, verbose_name='CBA series ID', blank=True)),
-                ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID', choices=[])),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(auto_now=True)),
-                ('broadcastformat', models.ForeignKey(related_name='shows', on_delete=models.CASCADE, verbose_name='Broadcast format', to='program.BroadcastFormat')),
-                ('hosts', models.ManyToManyField(related_name='shows', verbose_name='Hosts', to='program.Host', blank=True)),
-                ('musicfocus', models.ManyToManyField(related_name='shows', verbose_name='Music focus', to='program.MusicFocus', blank=True)),
-                ('owners', models.ManyToManyField(related_name='shows', verbose_name='Owners', to=settings.AUTH_USER_MODEL, blank=True)),
-                ('predecessor', models.ForeignKey(related_name='successors', on_delete=models.CASCADE, verbose_name='Predecessor', blank=True, to='program.Show', null=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("name", models.CharField(max_length=255, verbose_name="Name")),
+                (
+                    "slug",
+                    models.CharField(unique=True, max_length=255, verbose_name="Slug"),
+                ),
+                (
+                    "image",
+                    models.ImageField(
+                        upload_to=b"show_images",
+                        null=True,
+                        verbose_name="Image",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "image_enabled",
+                    models.BooleanField(default=True, verbose_name="show Image"),
+                ),
+                (
+                    "short_description",
+                    models.CharField(max_length=64, verbose_name="Short description"),
+                ),
+                (
+                    "description",
+                    models.TextField(null=True, verbose_name="Description", blank=True),
+                ),
+                (
+                    "email",
+                    models.EmailField(
+                        max_length=254, null=True, verbose_name="E-Mail", blank=True
+                    ),
+                ),
+                (
+                    "website",
+                    models.URLField(null=True, verbose_name="Website", blank=True),
+                ),
+                (
+                    "cba_series_id",
+                    models.IntegerField(
+                        null=True, verbose_name="CBA series ID", blank=True
+                    ),
+                ),
+                (
+                    "automation_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Automation ID", choices=[]
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("last_updated", models.DateTimeField(auto_now=True)),
+                (
+                    "broadcastformat",
+                    models.ForeignKey(
+                        related_name="shows",
+                        on_delete=models.CASCADE,
+                        verbose_name="Broadcast format",
+                        to="program.BroadcastFormat",
+                    ),
+                ),
+                (
+                    "hosts",
+                    models.ManyToManyField(
+                        related_name="shows",
+                        verbose_name="Hosts",
+                        to="program.Host",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "musicfocus",
+                    models.ManyToManyField(
+                        related_name="shows",
+                        verbose_name="Music focus",
+                        to="program.MusicFocus",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "owners",
+                    models.ManyToManyField(
+                        related_name="shows",
+                        verbose_name="Owners",
+                        to=settings.AUTH_USER_MODEL,
+                        blank=True,
+                    ),
+                ),
+                (
+                    "predecessor",
+                    models.ForeignKey(
+                        related_name="successors",
+                        on_delete=models.CASCADE,
+                        verbose_name="Predecessor",
+                        blank=True,
+                        to="program.Show",
+                        null=True,
+                    ),
+                ),
             ],
             options={
-                'ordering': ('slug',),
-                'verbose_name': 'Show',
-                'verbose_name_plural': 'Shows',
+                "ordering": ("slug",),
+                "verbose_name": "Show",
+                "verbose_name_plural": "Shows",
             },
         ),
         migrations.CreateModel(
-            name='ShowInformation',
+            name="ShowInformation",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('information', models.CharField(max_length=32, verbose_name='Information')),
-                ('abbrev', models.CharField(unique=True, max_length=4, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(unique=True, max_length=32, verbose_name='Slug')),
-                ('button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image', blank=True)),
-                ('button_hover', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image (hover)', blank=True)),
-                ('big_button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Big button image', blank=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                (
+                    "information",
+                    models.CharField(max_length=32, verbose_name="Information"),
+                ),
+                (
+                    "abbrev",
+                    models.CharField(
+                        unique=True, max_length=4, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(unique=True, max_length=32, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image (hover)",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Big button image",
+                        blank=True,
+                    ),
+                ),
             ],
             options={
-                'ordering': ('information',),
-                'verbose_name': 'Show information',
-                'verbose_name_plural': 'Show information',
+                "ordering": ("information",),
+                "verbose_name": "Show information",
+                "verbose_name_plural": "Show information",
             },
         ),
         migrations.CreateModel(
-            name='ShowTopic',
+            name="ShowTopic",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('topic', models.CharField(max_length=32, verbose_name='Show topic')),
-                ('abbrev', models.CharField(unique=True, max_length=4, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(unique=True, max_length=32, verbose_name='Slug')),
-                ('button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image', blank=True)),
-                ('button_hover', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Button image (hover)', blank=True)),
-                ('big_button', models.ImageField(upload_to=b'buttons', null=True, verbose_name='Big button image', blank=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("topic", models.CharField(max_length=32, verbose_name="Show topic")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        unique=True, max_length=4, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(unique=True, max_length=32, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Button image (hover)",
+                        blank=True,
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        upload_to=b"buttons",
+                        null=True,
+                        verbose_name="Big button image",
+                        blank=True,
+                    ),
+                ),
             ],
             options={
-                'ordering': ('topic',),
-                'verbose_name': 'Show topic',
-                'verbose_name_plural': 'Show topics',
+                "ordering": ("topic",),
+                "verbose_name": "Show topic",
+                "verbose_name_plural": "Show topics",
             },
         ),
         migrations.CreateModel(
-            name='TimeSlot',
+            name="TimeSlot",
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('start', models.DateTimeField(unique=True, verbose_name='Start time')),
-                ('end', models.DateTimeField(verbose_name='End time')),
-                ('programslot', models.ForeignKey(related_name='timeslots', on_delete=models.CASCADE, verbose_name='Program slot', to='program.ProgramSlot')),
-                ('show', models.ForeignKey(related_name='timeslots', on_delete=models.CASCADE, editable=False, to='program.Show')),
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                ("start", models.DateTimeField(unique=True, verbose_name="Start time")),
+                ("end", models.DateTimeField(verbose_name="End time")),
+                (
+                    "programslot",
+                    models.ForeignKey(
+                        related_name="timeslots",
+                        on_delete=models.CASCADE,
+                        verbose_name="Program slot",
+                        to="program.ProgramSlot",
+                    ),
+                ),
+                (
+                    "show",
+                    models.ForeignKey(
+                        related_name="timeslots",
+                        on_delete=models.CASCADE,
+                        editable=False,
+                        to="program.Show",
+                    ),
+                ),
             ],
             options={
-                'ordering': ('start', 'end'),
-                'verbose_name': 'Time slot',
-                'verbose_name_plural': 'Time slots',
+                "ordering": ("start", "end"),
+                "verbose_name": "Time slot",
+                "verbose_name_plural": "Time slots",
             },
         ),
         migrations.AddField(
-            model_name='show',
-            name='showinformation',
-            field=models.ManyToManyField(related_name='shows', verbose_name='Show information', to='program.ShowInformation', blank=True),
+            model_name="show",
+            name="showinformation",
+            field=models.ManyToManyField(
+                related_name="shows",
+                verbose_name="Show information",
+                to="program.ShowInformation",
+                blank=True,
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='showtopic',
-            field=models.ManyToManyField(related_name='shows', verbose_name='Show topic', to='program.ShowTopic', blank=True),
+            model_name="show",
+            name="showtopic",
+            field=models.ManyToManyField(
+                related_name="shows",
+                verbose_name="Show topic",
+                to="program.ShowTopic",
+                blank=True,
+            ),
         ),
         migrations.AddField(
-            model_name='programslot',
-            name='rrule',
-            field=models.ForeignKey(related_name='programslots', on_delete=models.CASCADE, verbose_name='Recurrence rule', to='program.RRule'),
+            model_name="programslot",
+            name="rrule",
+            field=models.ForeignKey(
+                related_name="programslots",
+                on_delete=models.CASCADE,
+                verbose_name="Recurrence rule",
+                to="program.RRule",
+            ),
         ),
         migrations.AddField(
-            model_name='programslot',
-            name='show',
-            field=models.ForeignKey(related_name='programslots', on_delete=models.CASCADE, verbose_name='Show', to='program.Show'),
+            model_name="programslot",
+            name="show",
+            field=models.ForeignKey(
+                related_name="programslots",
+                on_delete=models.CASCADE,
+                verbose_name="Show",
+                to="program.Show",
+            ),
         ),
         migrations.AddField(
-            model_name='note',
-            name='show',
-            field=models.ForeignKey(related_name='notes', on_delete=models.CASCADE, editable=False, to='program.Show'),
+            model_name="note",
+            name="show",
+            field=models.ForeignKey(
+                related_name="notes",
+                on_delete=models.CASCADE,
+                editable=False,
+                to="program.Show",
+            ),
         ),
         migrations.AddField(
-            model_name='note',
-            name='timeslot',
-            field=models.OneToOneField(verbose_name='Time slot', on_delete=models.CASCADE, to='program.TimeSlot'),
+            model_name="note",
+            name="timeslot",
+            field=models.OneToOneField(
+                verbose_name="Time slot",
+                on_delete=models.CASCADE,
+                to="program.TimeSlot",
+            ),
         ),
         migrations.AlterUniqueTogether(
-            name='programslot',
-            unique_together=set([('rrule', 'byweekday', 'dstart', 'tstart')]),
+            name="programslot",
+            unique_together=set([("rrule", "byweekday", "dstart", "tstart")]),
         ),
     ]
diff --git a/program/migrations/0001_squashed.py b/program/migrations/0001_squashed.py
index 7db3fbd6f60df1bf944cafbecea8741e27a77b8c..a231524b4b990776d05cbd5058a13321b62767e1 100644
--- a/program/migrations/0001_squashed.py
+++ b/program/migrations/0001_squashed.py
@@ -8,7 +8,30 @@ import versatileimagefield.fields
 
 class Migration(migrations.Migration):
 
-    replaces = [('program', '0001_initial'), ('program', '0002_host_is_always_visible'), ('program', '0003_host_is_active'), ('program', '0004_show_is_active'), ('program', '0005_programslot_is_active'), ('program', '0006_note_remove_cba_entry_id'), ('program', '0007_show_remove_cba_series_id'), ('program', '0008_show_remove_automation_id'), ('program', '0009_host_remove_is_active'), ('program', '0010_show_remove_is_active'), ('program', '0011_programslot_remove_is_active'), ('program', '0012_auto_20180104_0005'), ('program', '0013_auto_20180124_1748'), ('program', '0014_auto_20180216_2000'), ('program', '0015_auto_20180218_1111'), ('program', '0016_auto_20180222_1253'), ('program', '0017_auto_20180314_1409'), ('program', '0018_auto_20190810_1146'), ('program', '0019_auto_20190810_1340'), ('program', '0020_auto_20190810_1341'), ('program', '0021_show_is_active'), ('program', '0022_show_is_public')]
+    replaces = [
+        ("program", "0001_initial"),
+        ("program", "0002_host_is_always_visible"),
+        ("program", "0003_host_is_active"),
+        ("program", "0004_show_is_active"),
+        ("program", "0005_programslot_is_active"),
+        ("program", "0006_note_remove_cba_entry_id"),
+        ("program", "0007_show_remove_cba_series_id"),
+        ("program", "0008_show_remove_automation_id"),
+        ("program", "0009_host_remove_is_active"),
+        ("program", "0010_show_remove_is_active"),
+        ("program", "0011_programslot_remove_is_active"),
+        ("program", "0012_auto_20180104_0005"),
+        ("program", "0013_auto_20180124_1748"),
+        ("program", "0014_auto_20180216_2000"),
+        ("program", "0015_auto_20180218_1111"),
+        ("program", "0016_auto_20180222_1253"),
+        ("program", "0017_auto_20180314_1409"),
+        ("program", "0018_auto_20190810_1146"),
+        ("program", "0019_auto_20190810_1340"),
+        ("program", "0020_auto_20190810_1341"),
+        ("program", "0021_show_is_active"),
+        ("program", "0022_show_is_public"),
+    ]
 
     initial = True
 
@@ -18,324 +41,1104 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.CreateModel(
-            name='Host',
+            name="Host",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=128, verbose_name='Name')),
-                ('email', models.EmailField(blank=True, max_length=254, verbose_name='E-Mail')),
-                ('website', models.URLField(blank=True, help_text='URL to your personal website.', verbose_name='Website')),
-                ('biography', models.TextField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography')),
-                ('cba_url', models.URLField(blank=True, help_text='URL to your CBA profile.', verbose_name='CBA URL')),
-                ('dorftv_url', models.URLField(blank=True, help_text='URL to your dorfTV channel.', verbose_name='DorfTV URL')),
-                ('facebook_url', models.URLField(blank=True, help_text='URL to your Facebook profile.', verbose_name='Facebook URL')),
-                ('googleplus_url', models.URLField(blank=True, help_text='URL to your Google+ profile.', verbose_name='Google+ URL')),
-                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
-                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='host_images', verbose_name='Profile picture', width_field='width')),
-                ('linkedin_url', models.URLField(blank=True, help_text='URL to your LinkedIn profile.', verbose_name='LinkedIn URL')),
-                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
-                ('twitter_url', models.URLField(blank=True, help_text='URL to your Twitter profile.', verbose_name='Twitter URL')),
-                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
-                ('youtube_url', models.URLField(blank=True, help_text='URL to your Youtube channel.', verbose_name='Youtube URL')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=128, verbose_name="Name")),
+                (
+                    "email",
+                    models.EmailField(
+                        blank=True, max_length=254, verbose_name="E-Mail"
+                    ),
+                ),
+                (
+                    "website",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your personal website.",
+                        verbose_name="Website",
+                    ),
+                ),
+                (
+                    "biography",
+                    models.TextField(
+                        blank=True,
+                        help_text="Describe yourself and your fields of interest in a few"
+                                  " sentences.",
+                        null=True,
+                        verbose_name="Biography",
+                    ),
+                ),
+                (
+                    "cba_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your CBA profile.",
+                        verbose_name="CBA URL",
+                    ),
+                ),
+                (
+                    "dorftv_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your dorfTV channel.",
+                        verbose_name="DorfTV URL",
+                    ),
+                ),
+                (
+                    "facebook_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your Facebook profile.",
+                        verbose_name="Facebook URL",
+                    ),
+                ),
+                (
+                    "googleplus_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your Google+ profile.",
+                        verbose_name="Google+ URL",
+                    ),
+                ),
+                (
+                    "height",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Height",
+                    ),
+                ),
+                (
+                    "image",
+                    versatileimagefield.fields.VersatileImageField(
+                        blank=True,
+                        height_field="height",
+                        help_text="Upload a picture of yourself. Images are automatically cropped"
+                                  " around the 'Primary Point of Interest'. Click in the image to"
+                                  " change it and press Save.",
+                        null=True,
+                        upload_to="host_images",
+                        verbose_name="Profile picture",
+                        width_field="width",
+                    ),
+                ),
+                (
+                    "linkedin_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your LinkedIn profile.",
+                        verbose_name="LinkedIn URL",
+                    ),
+                ),
+                (
+                    "ppoi",
+                    versatileimagefield.fields.PPOIField(
+                        default="0.5x0.5",
+                        editable=False,
+                        max_length=20,
+                        verbose_name="Image PPOI",
+                    ),
+                ),
+                (
+                    "twitter_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your Twitter profile.",
+                        verbose_name="Twitter URL",
+                    ),
+                ),
+                (
+                    "width",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Width",
+                    ),
+                ),
+                (
+                    "youtube_url",
+                    models.URLField(
+                        blank=True,
+                        help_text="URL to your Youtube channel.",
+                        verbose_name="Youtube URL",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'ordering': ('name',),
-                'verbose_name': 'Host',
-                'verbose_name_plural': 'Hosts',
+                "ordering": ("name",),
+                "verbose_name": "Host",
+                "verbose_name_plural": "Hosts",
             },
         ),
         migrations.CreateModel(
-            name='MusicFocus',
+            name="MusicFocus",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('focus', models.CharField(max_length=32, verbose_name='Focus')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
-                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
-                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("focus", models.CharField(max_length=32, verbose_name="Focus")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image",
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image (hover)",
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Big button image",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'ordering': ('focus',),
-                'verbose_name': 'Music focus',
-                'verbose_name_plural': 'Music focus',
+                "ordering": ("focus",),
+                "verbose_name": "Music focus",
+                "verbose_name_plural": "Music focus",
             },
         ),
         migrations.CreateModel(
-            name='RRule',
+            name="RRule",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')),
-                ('freq', models.IntegerField(choices=[(1, 'Monthly'), (2, 'Weekly'), (3, 'Daily')], verbose_name='Frequency')),
-                ('interval', models.IntegerField(default=1, verbose_name='Interval')),
-                ('bysetpos', models.IntegerField(blank=True, choices=[(1, 'First'), (2, 'Second'), (3, 'Third'), (4, 'Fourth'), (5, 'Fifth'), (-1, 'Last')], null=True, verbose_name='Set position')),
-                ('count', models.IntegerField(blank=True, null=True, verbose_name='Count')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(max_length=32, unique=True, verbose_name="Name"),
+                ),
+                (
+                    "freq",
+                    models.IntegerField(
+                        choices=[(1, "Monthly"), (2, "Weekly"), (3, "Daily")],
+                        verbose_name="Frequency",
+                    ),
+                ),
+                ("interval", models.IntegerField(default=1, verbose_name="Interval")),
+                (
+                    "bysetpos",
+                    models.IntegerField(
+                        blank=True,
+                        choices=[
+                            (1, "First"),
+                            (2, "Second"),
+                            (3, "Third"),
+                            (4, "Fourth"),
+                            (5, "Fifth"),
+                            (-1, "Last"),
+                        ],
+                        null=True,
+                        verbose_name="Set position",
+                    ),
+                ),
+                (
+                    "count",
+                    models.IntegerField(blank=True, null=True, verbose_name="Count"),
+                ),
             ],
             options={
-                'ordering': ('pk',),
-                'verbose_name': 'Recurrence rule',
-                'verbose_name_plural': 'Recurrence rules',
+                "ordering": ("pk",),
+                "verbose_name": "Recurrence rule",
+                "verbose_name_plural": "Recurrence rules",
             },
         ),
         migrations.CreateModel(
-            name='Show',
+            name="Show",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(help_text="The show's name. Avoid a subtitle.", max_length=255, verbose_name='Name')),
-                ('slug', models.CharField(help_text='A simple to read URL for your show', max_length=255, unique=True, verbose_name='Slug')),
-                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='show_images', verbose_name='Image', width_field='width')),
-                ('short_description', models.TextField(help_text='Describe your show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description')),
-                ('description', models.TextField(blank=True, help_text='Describe your show in detail.', null=True, verbose_name='Description')),
-                ('email', models.EmailField(blank=True, help_text='The main contact email address for your show.', max_length=254, null=True, verbose_name='E-Mail')),
-                ('website', models.URLField(blank=True, help_text='Is there a website to your show? Type in its URL.', null=True, verbose_name='Website')),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(auto_now=True)),
-                ('hosts', models.ManyToManyField(blank=True, related_name='shows', to='program.Host', verbose_name='Hosts')),
-                ('musicfocus', models.ManyToManyField(blank=True, related_name='shows', to='program.MusicFocus', verbose_name='Music focus')),
-                ('owners', models.ManyToManyField(blank=True, related_name='shows', to=settings.AUTH_USER_MODEL, verbose_name='Owners')),
-                ('predecessor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='successors', to='program.Show', verbose_name='Predecessor')),
-                ('cba_series_id', models.IntegerField(blank=True, help_text='Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your ID under https://cba.fro.at/series', null=True, verbose_name='CBA Series ID')),
-                ('fallback_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback ID')),
-                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
-                ('logo', models.ImageField(blank=True, null=True, upload_to='show_images', verbose_name='Logo')),
-                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
-                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "name",
+                    models.CharField(
+                        help_text="The show's name. Avoid a subtitle.",
+                        max_length=255,
+                        verbose_name="Name",
+                    ),
+                ),
+                (
+                    "slug",
+                    models.CharField(
+                        help_text="A simple to read URL for your show",
+                        max_length=255,
+                        unique=True,
+                        verbose_name="Slug",
+                    ),
+                ),
+                (
+                    "image",
+                    versatileimagefield.fields.VersatileImageField(
+                        blank=True,
+                        height_field="height",
+                        help_text="Upload an image to your show. Images are automatically cropped"
+                                  " around the 'Primary Point of Interest'. Click in the image to"
+                                  " change it and press Save.",
+                        null=True,
+                        upload_to="show_images",
+                        verbose_name="Image",
+                        width_field="width",
+                    ),
+                ),
+                (
+                    "short_description",
+                    models.TextField(
+                        help_text="Describe your show in some sentences. Avoid technical data like"
+                                  " airing times and contact information. They will be added"
+                                  " automatically.",
+                        verbose_name="Short description",
+                    ),
+                ),
+                (
+                    "description",
+                    models.TextField(
+                        blank=True,
+                        help_text="Describe your show in detail.",
+                        null=True,
+                        verbose_name="Description",
+                    ),
+                ),
+                (
+                    "email",
+                    models.EmailField(
+                        blank=True,
+                        help_text="The main contact email address for your show.",
+                        max_length=254,
+                        null=True,
+                        verbose_name="E-Mail",
+                    ),
+                ),
+                (
+                    "website",
+                    models.URLField(
+                        blank=True,
+                        help_text="Is there a website to your show? Type in its URL.",
+                        null=True,
+                        verbose_name="Website",
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("last_updated", models.DateTimeField(auto_now=True)),
+                (
+                    "hosts",
+                    models.ManyToManyField(
+                        blank=True,
+                        related_name="shows",
+                        to="program.Host",
+                        verbose_name="Hosts",
+                    ),
+                ),
+                (
+                    "musicfocus",
+                    models.ManyToManyField(
+                        blank=True,
+                        related_name="shows",
+                        to="program.MusicFocus",
+                        verbose_name="Music focus",
+                    ),
+                ),
+                (
+                    "owners",
+                    models.ManyToManyField(
+                        blank=True,
+                        related_name="shows",
+                        to=settings.AUTH_USER_MODEL,
+                        verbose_name="Owners",
+                    ),
+                ),
+                (
+                    "predecessor",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="successors",
+                        to="program.Show",
+                        verbose_name="Predecessor",
+                    ),
+                ),
+                (
+                    "cba_series_id",
+                    models.IntegerField(
+                        blank=True,
+                        help_text="Link your show to a CBA series by giving its ID. This will"
+                                  " enable CBA upload and will automatically link your show to"
+                                  " your CBA archive. Find out your ID under"
+                                  " https://cba.fro.at/series",
+                        null=True,
+                        verbose_name="CBA Series ID",
+                    ),
+                ),
+                (
+                    "fallback_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Fallback ID"
+                    ),
+                ),
+                (
+                    "height",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Height",
+                    ),
+                ),
+                (
+                    "logo",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="show_images",
+                        verbose_name="Logo",
+                    ),
+                ),
+                (
+                    "ppoi",
+                    versatileimagefield.fields.PPOIField(
+                        default="0.5x0.5",
+                        editable=False,
+                        max_length=20,
+                        verbose_name="Image PPOI",
+                    ),
+                ),
+                (
+                    "width",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Width",
+                    ),
+                ),
             ],
             options={
-                'ordering': ('slug',),
-                'verbose_name': 'Show',
-                'verbose_name_plural': 'Shows',
+                "ordering": ("slug",),
+                "verbose_name": "Show",
+                "verbose_name_plural": "Shows",
             },
         ),
         migrations.CreateModel(
-            name='TimeSlot',
+            name="TimeSlot",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('start', models.DateTimeField(verbose_name='Start time')),
-                ('end', models.DateTimeField(verbose_name='End time')),
-                ('show', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.Show')),
-                ('is_repetition', models.BooleanField(default=False, verbose_name='REP')),
-                ('memo', models.TextField(blank=True, verbose_name='Memo')),
-                ('playlist_id', models.IntegerField(null=True, verbose_name='Playlist ID')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("start", models.DateTimeField(verbose_name="Start time")),
+                ("end", models.DateTimeField(verbose_name="End time")),
+                (
+                    "show",
+                    models.ForeignKey(
+                        editable=False,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="timeslots",
+                        to="program.Show",
+                    ),
+                ),
+                (
+                    "is_repetition",
+                    models.BooleanField(default=False, verbose_name="REP"),
+                ),
+                ("memo", models.TextField(blank=True, verbose_name="Memo")),
+                (
+                    "playlist_id",
+                    models.IntegerField(null=True, verbose_name="Playlist ID"),
+                ),
             ],
             options={
-                'ordering': ('start', 'end'),
-                'verbose_name': 'Time slot',
-                'verbose_name_plural': 'Time slots',
+                "ordering": ("start", "end"),
+                "verbose_name": "Time slot",
+                "verbose_name_plural": "Time slots",
             },
         ),
         migrations.CreateModel(
-            name='Category',
+            name="Category",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('category', models.CharField(max_length=32, verbose_name='Category')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('color', models.TextField(blank=True, max_length=7, verbose_name='Color')),
-                ('description', models.TextField(blank=True, verbose_name='Description')),
-                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
-                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
-                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("category", models.CharField(max_length=32, verbose_name="Category")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "color",
+                    models.TextField(blank=True, max_length=7, verbose_name="Color"),
+                ),
+                (
+                    "description",
+                    models.TextField(blank=True, verbose_name="Description"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image",
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image (hover)",
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Big button image",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Category',
-                'verbose_name_plural': 'Categories',
-                'ordering': ('category',),
+                "verbose_name": "Category",
+                "verbose_name_plural": "Categories",
+                "ordering": ("category",),
             },
         ),
         migrations.CreateModel(
-            name='Language',
+            name="Language",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=32, verbose_name='Language')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=32, verbose_name="Language")),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Language',
-                'verbose_name_plural': 'Languages',
-                'ordering': ('language',),
+                "verbose_name": "Language",
+                "verbose_name_plural": "Languages",
+                "ordering": ("language",),
             },
         ),
         migrations.CreateModel(
-            name='Schedule',
+            name="Schedule",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('byweekday', models.IntegerField(choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')], verbose_name='Weekday')),
-                ('dstart', models.DateField(verbose_name='First date')),
-                ('tstart', models.TimeField(verbose_name='Start time')),
-                ('tend', models.TimeField(verbose_name='End time')),
-                ('until', models.DateField(verbose_name='Last date')),
-                ('is_repetition', models.BooleanField(default=False, verbose_name='Is repetition')),
-                ('fallback_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback ID')),
-                ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID')),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('rrule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.RRule', verbose_name='Recurrence rule')),
-                ('show', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.Show', verbose_name='Show')),
-                ('add_business_days_only', models.BooleanField(default=False, verbose_name='Only add business days?')),
-                ('add_days_no', models.IntegerField(blank=True, null=True, verbose_name='Add days')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "byweekday",
+                    models.IntegerField(
+                        choices=[
+                            (0, "Monday"),
+                            (1, "Tuesday"),
+                            (2, "Wednesday"),
+                            (3, "Thursday"),
+                            (4, "Friday"),
+                            (5, "Saturday"),
+                            (6, "Sunday"),
+                        ],
+                        verbose_name="Weekday",
+                    ),
+                ),
+                ("dstart", models.DateField(verbose_name="First date")),
+                ("tstart", models.TimeField(verbose_name="Start time")),
+                ("tend", models.TimeField(verbose_name="End time")),
+                ("until", models.DateField(verbose_name="Last date")),
+                (
+                    "is_repetition",
+                    models.BooleanField(default=False, verbose_name="Is repetition"),
+                ),
+                (
+                    "fallback_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Fallback ID"
+                    ),
+                ),
+                (
+                    "automation_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Automation ID"
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True, null=True)),
+                ("last_updated", models.DateTimeField(auto_now=True, null=True)),
+                (
+                    "rrule",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="schedules",
+                        to="program.RRule",
+                        verbose_name="Recurrence rule",
+                    ),
+                ),
+                (
+                    "show",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="schedules",
+                        to="program.Show",
+                        verbose_name="Show",
+                    ),
+                ),
+                (
+                    "add_business_days_only",
+                    models.BooleanField(
+                        default=False, verbose_name="Only add business days?"
+                    ),
+                ),
+                (
+                    "add_days_no",
+                    models.IntegerField(blank=True, null=True, verbose_name="Add days"),
+                ),
             ],
             options={
-                'verbose_name': 'Schedule',
-                'verbose_name_plural': 'Schedules',
-                'ordering': ('dstart', 'tstart'),
+                "verbose_name": "Schedule",
+                "verbose_name_plural": "Schedules",
+                "ordering": ("dstart", "tstart"),
             },
         ),
         migrations.CreateModel(
-            name='Topic',
+            name="Topic",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('topic', models.CharField(max_length=32, verbose_name='Topic')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
-                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
-                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("topic", models.CharField(max_length=32, verbose_name="Topic")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image",
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image (hover)",
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Big button image",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Topic',
-                'verbose_name_plural': 'Topics',
-                'ordering': ('topic',),
+                "verbose_name": "Topic",
+                "verbose_name_plural": "Topics",
+                "ordering": ("topic",),
             },
         ),
         migrations.CreateModel(
-            name='Type',
+            name="Type",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('type', models.CharField(max_length=32, verbose_name='Type')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('color', models.CharField(default='#ffffff', max_length=7, verbose_name='Color')),
-                ('text_color', models.CharField(default='#000000', max_length=7, verbose_name='Text color')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("type", models.CharField(max_length=32, verbose_name="Type")),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "color",
+                    models.CharField(
+                        default="#ffffff", max_length=7, verbose_name="Color"
+                    ),
+                ),
+                (
+                    "text_color",
+                    models.CharField(
+                        default="#000000", max_length=7, verbose_name="Text color"
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Type',
-                'verbose_name_plural': 'Types',
-                'ordering': ('type',),
+                "verbose_name": "Type",
+                "verbose_name_plural": "Types",
+                "ordering": ("type",),
             },
         ),
         migrations.CreateModel(
-            name='Note',
+            name="Note",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('title', models.CharField(help_text="Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>Avoid technical data like the show's name, its airing times or its episode number. These data are added automatically.", max_length=128, verbose_name='Title')),
-                ('content', models.TextField(help_text='Describe your upcoming show in detail.', verbose_name='Content')),
-                ('status', models.IntegerField(choices=[(0, 'Cancellation'), (1, 'Recommendation'), (2, 'Repetition')], default=1, verbose_name='Status')),
-                ('start', models.DateTimeField(editable=False)),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(auto_now=True)),
-                ('show', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='program.Show')),
-                ('timeslot', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='program.TimeSlot', verbose_name='Time slot')),
-                ('audio_url', models.TextField(blank=True, editable=False, verbose_name='Direct URL to a linked audio file')),
-                ('cba_id', models.IntegerField(blank=True, help_text="Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)", null=True, verbose_name='CBA ID')),
-                ('height', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height')),
-                ('host', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hosts', to='program.Host')),
-                ('image', versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your note. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='note_images', verbose_name='Featured image', width_field='width')),
-                ('ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI')),
-                ('slug', models.SlugField(default=1, help_text='A simple to read URL for your show.', max_length=32, unique=True, verbose_name='Slug')),
-                ('summary', models.TextField(blank=True, help_text='Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Summary')),
-                ('user', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='users', to=settings.AUTH_USER_MODEL)),
-                ('width', models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "title",
+                    models.CharField(
+                        help_text="Give your note a good headline. What will your upcoming show be"
+                                  " about? Try to arouse interest to listen to it!<br>Avoid"
+                                  " technical data like the show's name, its airing times or its"
+                                  " episode number. These data are added automatically.",
+                        max_length=128,
+                        verbose_name="Title",
+                    ),
+                ),
+                (
+                    "content",
+                    models.TextField(
+                        help_text="Describe your upcoming show in detail.",
+                        verbose_name="Content",
+                    ),
+                ),
+                (
+                    "status",
+                    models.IntegerField(
+                        choices=[
+                            (0, "Cancellation"),
+                            (1, "Recommendation"),
+                            (2, "Repetition"),
+                        ],
+                        default=1,
+                        verbose_name="Status",
+                    ),
+                ),
+                ("start", models.DateTimeField(editable=False)),
+                ("created", models.DateTimeField(auto_now_add=True)),
+                ("last_updated", models.DateTimeField(auto_now=True)),
+                (
+                    "show",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="notes",
+                        to="program.Show",
+                    ),
+                ),
+                (
+                    "timeslot",
+                    models.OneToOneField(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="program.TimeSlot",
+                        verbose_name="Time slot",
+                    ),
+                ),
+                (
+                    "audio_url",
+                    models.TextField(
+                        blank=True,
+                        editable=False,
+                        verbose_name="Direct URL to a linked audio file",
+                    ),
+                ),
+                (
+                    "cba_id",
+                    models.IntegerField(
+                        blank=True,
+                        help_text="Link the note to a certain CBA post by giving its ID. (E.g. if"
+                                  " your post's CBA URL is https://cba.fro.at/1234, then your CBA"
+                                  " ID is 1234)",
+                        null=True,
+                        verbose_name="CBA ID",
+                    ),
+                ),
+                (
+                    "height",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Height",
+                    ),
+                ),
+                (
+                    "host",
+                    models.ForeignKey(
+                        null=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="hosts",
+                        to="program.Host",
+                    ),
+                ),
+                (
+                    "image",
+                    versatileimagefield.fields.VersatileImageField(
+                        blank=True,
+                        height_field="height",
+                        help_text="Upload an image to your note. Images are automatically cropped"
+                                  " around the 'Primary Point of Interest'. Click in the image to"
+                                  " change it and press Save.",
+                        null=True,
+                        upload_to="note_images",
+                        verbose_name="Featured image",
+                        width_field="width",
+                    ),
+                ),
+                (
+                    "ppoi",
+                    versatileimagefield.fields.PPOIField(
+                        default="0.5x0.5",
+                        editable=False,
+                        max_length=20,
+                        verbose_name="Image PPOI",
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(
+                        default=1,
+                        help_text="A simple to read URL for your show.",
+                        max_length=32,
+                        unique=True,
+                        verbose_name="Slug",
+                    ),
+                ),
+                (
+                    "summary",
+                    models.TextField(
+                        blank=True,
+                        help_text="Describe your upcoming show in some sentences. Avoid technical"
+                                  " data like airing times and contact information. They will be"
+                                  " added automatically.",
+                        verbose_name="Summary",
+                    ),
+                ),
+                (
+                    "user",
+                    models.ForeignKey(
+                        default=1,
+                        editable=False,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="users",
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+                (
+                    "width",
+                    models.PositiveIntegerField(
+                        blank=True,
+                        editable=False,
+                        null=True,
+                        verbose_name="Image Width",
+                    ),
+                ),
             ],
             options={
-                'ordering': ('timeslot',),
-                'verbose_name': 'Note',
-                'verbose_name_plural': 'Notes',
+                "ordering": ("timeslot",),
+                "verbose_name": "Note",
+                "verbose_name_plural": "Notes",
             },
         ),
         migrations.AddField(
-            model_name='show',
-            name='category',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Category', verbose_name='Category'),
+            model_name="show",
+            name="category",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="shows",
+                to="program.Category",
+                verbose_name="Category",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='language',
-            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language', verbose_name='Language'),
+            model_name="show",
+            name="language",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="language",
+                to="program.Language",
+                verbose_name="Language",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='topic',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Topic', verbose_name='Topic'),
+            model_name="show",
+            name="topic",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="shows",
+                to="program.Topic",
+                verbose_name="Topic",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='type',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.Type', verbose_name='Type'),
+            model_name="show",
+            name="type",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.Type",
+                verbose_name="Type",
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='schedule',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.Schedule', verbose_name='Schedule'),
+            model_name="timeslot",
+            name="schedule",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="timeslots",
+                to="program.Schedule",
+                verbose_name="Schedule",
+            ),
             preserve_default=False,
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='is_repetition',
-            field=models.BooleanField(default=False, verbose_name='(REP)'),
+            model_name="timeslot",
+            name="is_repetition",
+            field=models.BooleanField(default=False, verbose_name="(REP)"),
         ),
         migrations.CreateModel(
-            name='FundingCategory',
+            name="FundingCategory",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('fundingcategory', models.CharField(max_length=32, verbose_name='Funding Category')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "fundingcategory",
+                    models.CharField(max_length=32, verbose_name="Funding Category"),
+                ),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Funding Category',
-                'verbose_name_plural': 'Funding Categories',
-                'ordering': ('fundingcategory',),
+                "verbose_name": "Funding Category",
+                "verbose_name_plural": "Funding Categories",
+                "ordering": ("fundingcategory",),
             },
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='note_id',
-            field=models.IntegerField(editable=False, null=True, verbose_name='Note ID'),
+            model_name="timeslot",
+            name="note_id",
+            field=models.IntegerField(
+                editable=False, null=True, verbose_name="Note ID"
+            ),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='is_repetition',
-            field=models.BooleanField(default=False, verbose_name='Is repetition?'),
+            model_name="timeslot",
+            name="is_repetition",
+            field=models.BooleanField(default=False, verbose_name="Is repetition?"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='cba_series_id',
-            field=models.IntegerField(blank=True, help_text="Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your show's ID under https://cba.fro.at/series", null=True, verbose_name='CBA Series ID'),
+            model_name="show",
+            name="cba_series_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="Link your show to a CBA series by giving its ID. This will enable CBA"
+                          " upload and will automatically link your show to your CBA archive. Find"
+                          " out your show's ID under https://cba.fro.at/series",
+                null=True,
+                verbose_name="CBA Series ID",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='fallback_id',
-            field=models.IntegerField(blank=True, help_text='If a timeslot of your show is empty, this playlist will be aired as a backup.', null=True, verbose_name='Fallback ID'),
+            model_name="show",
+            name="fallback_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="If a timeslot of your show is empty, this playlist will be aired as a"
+                          " backup.",
+                null=True,
+                verbose_name="Fallback ID",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='logo',
-            field=models.ImageField(blank=True, help_text='Upload a logo of your show.', null=True, upload_to='show_images', verbose_name='Logo'),
+            model_name="show",
+            name="logo",
+            field=models.ImageField(
+                blank=True,
+                help_text="Upload a logo of your show.",
+                null=True,
+                upload_to="show_images",
+                verbose_name="Logo",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='short_description',
-            field=models.TextField(help_text='Describe your show for your listeners in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description'),
+            model_name="show",
+            name="short_description",
+            field=models.TextField(
+                help_text="Describe your show for your listeners in some sentences. Avoid"
+                          " technical data like airing times and contact information. They will be"
+                          " added automatically.",
+                verbose_name="Short description",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='fundingcategory',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.FundingCategory', verbose_name='Funding Category'),
+            model_name="show",
+            name="fundingcategory",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.FundingCategory",
+                verbose_name="Funding Category",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="show",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='show',
-            name='is_public',
-            field=models.BooleanField(default=False, help_text='Files and Playlists of Public Shows can only be changed by owners but may be used by everyone.', verbose_name='Is Public?'),
+            model_name="show",
+            name="is_public",
+            field=models.BooleanField(
+                default=False,
+                help_text="Files and Playlists of Public Shows can only be changed by owners but"
+                          " may be used by everyone.",
+                verbose_name="Is Public?",
+            ),
         ),
     ]
diff --git a/program/migrations/0002_auto_20210426_2345.py b/program/migrations/0002_auto_20210426_2345.py
index 4d67419dded6a1761da498a4a4869b48a8affb08..12d9e83f8d680ad8ed427180dd2db47a1a55367a 100644
--- a/program/migrations/0002_auto_20210426_2345.py
+++ b/program/migrations/0002_auto_20210426_2345.py
@@ -6,18 +6,14 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0001_squashed'),
+        ("program", "0001_squashed"),
     ]
 
     operations = [
         migrations.RenameField(
-            model_name='schedule',
-            old_name='fallback_id',
-            new_name='default_id'
+            model_name="schedule", old_name="fallback_id", new_name="default_id"
         ),
         migrations.RenameField(
-            model_name='show',
-            old_name='fallback_id',
-            new_name='default_id'
+            model_name="show", old_name="fallback_id", new_name="default_id"
         ),
     ]
diff --git a/program/migrations/0002_host_is_always_visible.py b/program/migrations/0002_host_is_always_visible.py
index 9abf2bdc3474a1e7a4f72c8ce794d90af18bde69..c2cb3345ca92a17f28398bff490acfc906ecbd6e 100644
--- a/program/migrations/0002_host_is_always_visible.py
+++ b/program/migrations/0002_host_is_always_visible.py
@@ -7,13 +7,13 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0001_initial'),
+        ("program", "0001_initial"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='host',
-            name='is_always_visible',
-            field=models.BooleanField(default=False, verbose_name='Is always visible'),
+            model_name="host",
+            name="is_always_visible",
+            field=models.BooleanField(default=False, verbose_name="Is always visible"),
         ),
     ]
diff --git a/program/migrations/0003_auto_20210713_0420.py b/program/migrations/0003_auto_20210713_0420.py
index 88314acb966c742fcfffba664e8b59a8a37e7064..ab1047726171190c774bd382992f253e110ed431 100644
--- a/program/migrations/0003_auto_20210713_0420.py
+++ b/program/migrations/0003_auto_20210713_0420.py
@@ -6,18 +6,14 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0002_auto_20210426_2345'),
+        ("program", "0002_auto_20210426_2345"),
     ]
 
     operations = [
         migrations.RenameField(
-            model_name='schedule',
-            old_name='default_id',
-            new_name='default_playlist_id'
+            model_name="schedule", old_name="default_id", new_name="default_playlist_id"
         ),
         migrations.RenameField(
-            model_name='show',
-            old_name='default_id',
-            new_name='default_playlist_id'
+            model_name="show", old_name="default_id", new_name="default_playlist_id"
         ),
     ]
diff --git a/program/migrations/0003_host_is_active.py b/program/migrations/0003_host_is_active.py
index 28c10498165c454ea33dfa51df3bbd3e5c12dab6..ef977a8827de9b71e95f7a27a8116d043736e328 100644
--- a/program/migrations/0003_host_is_active.py
+++ b/program/migrations/0003_host_is_active.py
@@ -7,13 +7,15 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0002_host_is_always_visible'),
+        ("program", "0002_host_is_always_visible"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='host',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active', editable=False),
+            model_name="host",
+            name="is_active",
+            field=models.BooleanField(
+                default=True, verbose_name="Is active", editable=False
+            ),
         ),
     ]
diff --git a/program/migrations/0004_auto_20220111_1806.py b/program/migrations/0004_auto_20220111_1806.py
index 2a7706ec083650189d750ffe644cda877fe57dda..cb6e547ba1f6b0aa1282d36c0d957c8b7d898803 100644
--- a/program/migrations/0004_auto_20220111_1806.py
+++ b/program/migrations/0004_auto_20220111_1806.py
@@ -6,59 +6,72 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0003_auto_20210713_0420'),
+        ("program", "0003_auto_20210713_0420"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='category',
-            name='big_button',
+            model_name="category",
+            name="big_button",
         ),
         migrations.RemoveField(
-            model_name='category',
-            name='button',
+            model_name="category",
+            name="button",
         ),
         migrations.RemoveField(
-            model_name='category',
-            name='button_hover',
+            model_name="category",
+            name="button_hover",
         ),
         migrations.RemoveField(
-            model_name='musicfocus',
-            name='big_button',
+            model_name="musicfocus",
+            name="big_button",
         ),
         migrations.RemoveField(
-            model_name='musicfocus',
-            name='button',
+            model_name="musicfocus",
+            name="button",
         ),
         migrations.RemoveField(
-            model_name='musicfocus',
-            name='button_hover',
+            model_name="musicfocus",
+            name="button_hover",
         ),
         migrations.RemoveField(
-            model_name='topic',
-            name='big_button',
+            model_name="topic",
+            name="big_button",
         ),
         migrations.RemoveField(
-            model_name='topic',
-            name='button',
+            model_name="topic",
+            name="button",
         ),
         migrations.RemoveField(
-            model_name='topic',
-            name='button_hover',
+            model_name="topic",
+            name="button_hover",
         ),
         migrations.AlterField(
-            model_name='note',
-            name='slug',
-            field=models.SlugField(help_text='A simple to read URL for your show.', max_length=32, unique=True, verbose_name='Slug'),
+            model_name="note",
+            name="slug",
+            field=models.SlugField(
+                help_text="A simple to read URL for your show.",
+                max_length=32,
+                unique=True,
+                verbose_name="Slug",
+            ),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='default_playlist_id',
-            field=models.IntegerField(blank=True, null=True, verbose_name='Default Playlist ID'),
+            model_name="schedule",
+            name="default_playlist_id",
+            field=models.IntegerField(
+                blank=True, null=True, verbose_name="Default Playlist ID"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='default_playlist_id',
-            field=models.IntegerField(blank=True, help_text='If a timeslot of your show is empty, this playlist will be aired as a backup.', null=True, verbose_name='Default Playlist ID'),
+            model_name="show",
+            name="default_playlist_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="If a timeslot of your show is empty, this playlist will be aired as a"
+                          " backup.",
+                null=True,
+                verbose_name="Default Playlist ID",
+            ),
         ),
     ]
diff --git a/program/migrations/0004_show_is_active.py b/program/migrations/0004_show_is_active.py
index 26e32052e8c0d8e1851c41e891f69c4afbbfaef8..2d27dcae933a2fc1ec6e5e7186352677f84d4de5 100644
--- a/program/migrations/0004_show_is_active.py
+++ b/program/migrations/0004_show_is_active.py
@@ -7,13 +7,15 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0003_host_is_active'),
+        ("program", "0003_host_is_active"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='show',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active', editable=False),
+            model_name="show",
+            name="is_active",
+            field=models.BooleanField(
+                default=True, verbose_name="Is active", editable=False
+            ),
         ),
     ]
diff --git a/program/migrations/0005_auto_20220111_2251.py b/program/migrations/0005_auto_20220111_2251.py
index 7e8f05762640cf12de5002ed54faa0a33f8ae5b0..2d6a50f419e8ce0557fde4e82094ee9ea420e631 100644
--- a/program/migrations/0005_auto_20220111_2251.py
+++ b/program/migrations/0005_auto_20220111_2251.py
@@ -6,16 +6,16 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0004_auto_20220111_1806'),
+        ("program", "0004_auto_20220111_1806"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='type',
-            name='color',
+            model_name="type",
+            name="color",
         ),
         migrations.RemoveField(
-            model_name='type',
-            name='text_color',
+            model_name="type",
+            name="text_color",
         ),
     ]
diff --git a/program/migrations/0005_programslot_is_active.py b/program/migrations/0005_programslot_is_active.py
index 31975c8034e4494d03a907f8bb70c7a48f3c60ac..04ca314a26ad6e4178b0dfdc0765bcb6e5c2323b 100644
--- a/program/migrations/0005_programslot_is_active.py
+++ b/program/migrations/0005_programslot_is_active.py
@@ -7,13 +7,15 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0004_show_is_active'),
+        ("program", "0004_show_is_active"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='programslot',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active', editable=False),
+            model_name="programslot",
+            name="is_active",
+            field=models.BooleanField(
+                default=True, verbose_name="Is active", editable=False
+            ),
         ),
     ]
diff --git a/program/migrations/0006_note_remove_cba_entry_id.py b/program/migrations/0006_note_remove_cba_entry_id.py
index d04be5732e78e534bbe00d36d88fa86c766959ad..3d478b2a4e307f0473ce627e68814c5ae1d82afa 100644
--- a/program/migrations/0006_note_remove_cba_entry_id.py
+++ b/program/migrations/0006_note_remove_cba_entry_id.py
@@ -7,12 +7,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0005_programslot_is_active'),
+        ("program", "0005_programslot_is_active"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='note',
-            name='cba_entry_id',
+            model_name="note",
+            name="cba_entry_id",
         ),
     ]
diff --git a/program/migrations/0006_remove_category_color.py b/program/migrations/0006_remove_category_color.py
index e7293b83261bca335b20d472cc9ae7b376d5bee4..4d09474e8c5c776f16c0d5f6409f33d9fd3a0124 100644
--- a/program/migrations/0006_remove_category_color.py
+++ b/program/migrations/0006_remove_category_color.py
@@ -6,12 +6,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0005_auto_20220111_2251'),
+        ("program", "0005_auto_20220111_2251"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='category',
-            name='color',
+            model_name="category",
+            name="color",
         ),
     ]
diff --git a/program/migrations/0007_auto_20220112_2335.py b/program/migrations/0007_auto_20220112_2335.py
index 778ac552cd8d6de792450f113c668f272d22ff62..f635a3be8f8e0f923b09cc52805db7f5b3b7736f 100644
--- a/program/migrations/0007_auto_20220112_2335.py
+++ b/program/migrations/0007_auto_20220112_2335.py
@@ -6,23 +6,36 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0006_remove_category_color'),
+        ("program", "0006_remove_category_color"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='host',
-            name='biography',
-            field=models.TextField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography'),
+            model_name="host",
+            name="biography",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe yourself and your fields of interest in a few sentences.",
+                null=True,
+                verbose_name="Biography",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='content',
-            field=models.TextField(help_text='Describe your upcoming show in detail.', verbose_name='Content'),
+            model_name="note",
+            name="content",
+            field=models.TextField(
+                help_text="Describe your upcoming show in detail.",
+                verbose_name="Content",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='description',
-            field=models.TextField(blank=True, help_text='Describe your show in detail.', null=True, verbose_name='Description'),
+            model_name="show",
+            name="description",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe your show in detail.",
+                null=True,
+                verbose_name="Description",
+            ),
         ),
     ]
diff --git a/program/migrations/0007_show_remove_cba_series_id.py b/program/migrations/0007_show_remove_cba_series_id.py
index 1173b51079fdb2197814b611b08a85a6a8d8a9a4..346acbb3b6b2ad25a45c05db459f21dda36bb06b 100644
--- a/program/migrations/0007_show_remove_cba_series_id.py
+++ b/program/migrations/0007_show_remove_cba_series_id.py
@@ -7,12 +7,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0006_note_remove_cba_entry_id'),
+        ("program", "0006_note_remove_cba_entry_id"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='show',
-            name='cba_series_id',
+            model_name="show",
+            name="cba_series_id",
         ),
     ]
diff --git a/program/migrations/0008_auto_20220117_1721.py b/program/migrations/0008_auto_20220117_1721.py
index 90e986aea1a68741fd59d4c8e281616cdf7660b8..d5f39e87907759b04bc03c5861ee25b8ff510f01 100644
--- a/program/migrations/0008_auto_20220117_1721.py
+++ b/program/migrations/0008_auto_20220117_1721.py
@@ -7,143 +7,172 @@ import versatileimagefield.fields
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0007_auto_20220112_2335'),
+        ("program", "0007_auto_20220112_2335"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='host',
-            name='biography',
-            field=models.TextField(blank=True, null=True, verbose_name='Biography'),
+            model_name="host",
+            name="biography",
+            field=models.TextField(blank=True, null=True, verbose_name="Biography"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='cba_url',
-            field=models.URLField(blank=True, verbose_name='CBA URL'),
+            model_name="host",
+            name="cba_url",
+            field=models.URLField(blank=True, verbose_name="CBA URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='dorftv_url',
-            field=models.URLField(blank=True, verbose_name='DorfTV URL'),
+            model_name="host",
+            name="dorftv_url",
+            field=models.URLField(blank=True, verbose_name="DorfTV URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='facebook_url',
-            field=models.URLField(blank=True, verbose_name='Facebook URL'),
+            model_name="host",
+            name="facebook_url",
+            field=models.URLField(blank=True, verbose_name="Facebook URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='googleplus_url',
-            field=models.URLField(blank=True, verbose_name='Google+ URL'),
+            model_name="host",
+            name="googleplus_url",
+            field=models.URLField(blank=True, verbose_name="Google+ URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='host_images', verbose_name='Profile picture', width_field='width'),
+            model_name="host",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="host_images",
+                verbose_name="Profile picture",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='linkedin_url',
-            field=models.URLField(blank=True, verbose_name='LinkedIn URL'),
+            model_name="host",
+            name="linkedin_url",
+            field=models.URLField(blank=True, verbose_name="LinkedIn URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='twitter_url',
-            field=models.URLField(blank=True, verbose_name='Twitter URL'),
+            model_name="host",
+            name="twitter_url",
+            field=models.URLField(blank=True, verbose_name="Twitter URL"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='website',
-            field=models.URLField(blank=True, verbose_name='Website'),
+            model_name="host",
+            name="website",
+            field=models.URLField(blank=True, verbose_name="Website"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='youtube_url',
-            field=models.URLField(blank=True, verbose_name='Youtube URL'),
+            model_name="host",
+            name="youtube_url",
+            field=models.URLField(blank=True, verbose_name="Youtube URL"),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='cba_id',
-            field=models.IntegerField(blank=True, null=True, verbose_name='CBA ID'),
+            model_name="note",
+            name="cba_id",
+            field=models.IntegerField(blank=True, null=True, verbose_name="CBA ID"),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='content',
-            field=models.TextField(verbose_name='Content'),
+            model_name="note",
+            name="content",
+            field=models.TextField(verbose_name="Content"),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='note_images', verbose_name='Featured image', width_field='width'),
+            model_name="note",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="note_images",
+                verbose_name="Featured image",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='slug',
-            field=models.SlugField(max_length=32, unique=True, verbose_name='Slug'),
+            model_name="note",
+            name="slug",
+            field=models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='summary',
-            field=models.TextField(blank=True, verbose_name='Summary'),
+            model_name="note",
+            name="summary",
+            field=models.TextField(blank=True, verbose_name="Summary"),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='title',
-            field=models.CharField(max_length=128, verbose_name='Title'),
+            model_name="note",
+            name="title",
+            field=models.CharField(max_length=128, verbose_name="Title"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='cba_series_id',
-            field=models.IntegerField(blank=True, null=True, verbose_name='CBA Series ID'),
+            model_name="show",
+            name="cba_series_id",
+            field=models.IntegerField(
+                blank=True, null=True, verbose_name="CBA Series ID"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='default_playlist_id',
-            field=models.IntegerField(blank=True, null=True, verbose_name='Default Playlist ID'),
+            model_name="show",
+            name="default_playlist_id",
+            field=models.IntegerField(
+                blank=True, null=True, verbose_name="Default Playlist ID"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='description',
-            field=models.TextField(blank=True, null=True, verbose_name='Description'),
+            model_name="show",
+            name="description",
+            field=models.TextField(blank=True, null=True, verbose_name="Description"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='email',
-            field=models.EmailField(blank=True, max_length=254, null=True, verbose_name='E-Mail'),
+            model_name="show",
+            name="email",
+            field=models.EmailField(
+                blank=True, max_length=254, null=True, verbose_name="E-Mail"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='show_images', verbose_name='Image', width_field='width'),
+            model_name="show",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="show_images",
+                verbose_name="Image",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='is_public',
-            field=models.BooleanField(default=False, verbose_name='Is Public?'),
+            model_name="show",
+            name="is_public",
+            field=models.BooleanField(default=False, verbose_name="Is Public?"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='logo',
-            field=models.ImageField(blank=True, null=True, upload_to='show_images', verbose_name='Logo'),
+            model_name="show",
+            name="logo",
+            field=models.ImageField(
+                blank=True, null=True, upload_to="show_images", verbose_name="Logo"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='name',
-            field=models.CharField(max_length=255, verbose_name='Name'),
+            model_name="show",
+            name="name",
+            field=models.CharField(max_length=255, verbose_name="Name"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='short_description',
-            field=models.TextField(verbose_name='Short description'),
+            model_name="show",
+            name="short_description",
+            field=models.TextField(verbose_name="Short description"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='slug',
-            field=models.CharField(max_length=255, unique=True, verbose_name='Slug'),
+            model_name="show",
+            name="slug",
+            field=models.CharField(max_length=255, unique=True, verbose_name="Slug"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='website',
-            field=models.URLField(blank=True, null=True, verbose_name='Website'),
+            model_name="show",
+            name="website",
+            field=models.URLField(blank=True, null=True, verbose_name="Website"),
         ),
     ]
diff --git a/program/migrations/0008_show_remove_automation_id.py b/program/migrations/0008_show_remove_automation_id.py
index eda14c51e6f3e6b5f0dfe32a44346a635305757d..db0a6f0fa362aea0de24036774113dc7d7667d3d 100644
--- a/program/migrations/0008_show_remove_automation_id.py
+++ b/program/migrations/0008_show_remove_automation_id.py
@@ -1,18 +1,18 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import migrations, models
+from django.db import migrations
 
 
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0007_show_remove_cba_series_id'),
+        ("program", "0007_show_remove_cba_series_id"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='show',
-            name='automation_id',
+            model_name="show",
+            name="automation_id",
         ),
     ]
diff --git a/program/migrations/0009_auto_20220124_2211.py b/program/migrations/0009_auto_20220124_2211.py
index 3ca882551f8a9749bdcd78e63a7ace77bb6c0193..2469d57e06d540f08251f3093478261759229f56 100644
--- a/program/migrations/0009_auto_20220124_2211.py
+++ b/program/migrations/0009_auto_20220124_2211.py
@@ -6,41 +6,43 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0008_auto_20220117_1721'),
+        ("program", "0008_auto_20220117_1721"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='host',
-            name='cba_url',
+            model_name="host",
+            name="cba_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='dorftv_url',
+            model_name="host",
+            name="dorftv_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='facebook_url',
+            model_name="host",
+            name="facebook_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='googleplus_url',
+            model_name="host",
+            name="googleplus_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='linkedin_url',
+            model_name="host",
+            name="linkedin_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='twitter_url',
+            model_name="host",
+            name="twitter_url",
         ),
         migrations.RemoveField(
-            model_name='host',
-            name='youtube_url',
+            model_name="host",
+            name="youtube_url",
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='automation_id',
-            field=models.IntegerField(blank=True, choices=[], null=True, verbose_name='Automation ID'),
+            model_name="schedule",
+            name="automation_id",
+            field=models.IntegerField(
+                blank=True, choices=[], null=True, verbose_name="Automation ID"
+            ),
         ),
     ]
diff --git a/program/migrations/0009_host_remove_is_active.py b/program/migrations/0009_host_remove_is_active.py
index f6647f04428ae3bbf55a7373e4d3e2b1f47b78d7..589c3d9afb8e2dd21571d0852d84d52509944680 100644
--- a/program/migrations/0009_host_remove_is_active.py
+++ b/program/migrations/0009_host_remove_is_active.py
@@ -7,12 +7,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0008_show_remove_automation_id'),
+        ("program", "0008_show_remove_automation_id"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='host',
-            name='is_active',
+            model_name="host",
+            name="is_active",
         ),
     ]
diff --git a/program/migrations/0010_remove_schedule_automation_id.py b/program/migrations/0010_remove_schedule_automation_id.py
index e90f4eee718979b4939bc1cb069ec0588082b439..0e5e24f9c70cbb9ed2458e7d34e58d5fbb0f7ecd 100644
--- a/program/migrations/0010_remove_schedule_automation_id.py
+++ b/program/migrations/0010_remove_schedule_automation_id.py
@@ -6,12 +6,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0009_auto_20220124_2211'),
+        ("program", "0009_auto_20220124_2211"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='schedule',
-            name='automation_id',
+            model_name="schedule",
+            name="automation_id",
         ),
     ]
diff --git a/program/migrations/0010_show_remove_is_active.py b/program/migrations/0010_show_remove_is_active.py
index 543bdc1d54958b2a0aba648a40f9d5612f57e47e..9ee6ecf86c94c250bde28a22b867729d4d7fa67b 100644
--- a/program/migrations/0010_show_remove_is_active.py
+++ b/program/migrations/0010_show_remove_is_active.py
@@ -7,12 +7,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0009_host_remove_is_active'),
+        ("program", "0009_host_remove_is_active"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='show',
-            name='is_active',
+            model_name="show",
+            name="is_active",
         ),
     ]
diff --git a/program/migrations/0011_link.py b/program/migrations/0011_link.py
index 7260948af89eed73dfcf104dd2047bcbd201fe4c..209ff5fd2df610f536cfcc96e0b8b82b7ae643b5 100644
--- a/program/migrations/0011_link.py
+++ b/program/migrations/0011_link.py
@@ -7,17 +7,32 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0010_remove_schedule_automation_id'),
+        ("program", "0010_remove_schedule_automation_id"),
     ]
 
     operations = [
         migrations.CreateModel(
-            name='Link',
+            name="Link",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('description', models.CharField(max_length=8)),
-                ('url', models.URLField()),
-                ('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='links', to='program.host')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("description", models.CharField(max_length=8)),
+                ("url", models.URLField()),
+                (
+                    "host",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="links",
+                        to="program.host",
+                    ),
+                ),
             ],
         ),
     ]
diff --git a/program/migrations/0011_programslot_remove_is_active.py b/program/migrations/0011_programslot_remove_is_active.py
index f73a01ee3e92eb4c9a4ebb9332a63d1d080785ab..a987de5447afdec584a4be0e34c11391793d7449 100644
--- a/program/migrations/0011_programslot_remove_is_active.py
+++ b/program/migrations/0011_programslot_remove_is_active.py
@@ -7,12 +7,12 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0010_show_remove_is_active'),
+        ("program", "0010_show_remove_is_active"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='programslot',
-            name='is_active',
+            model_name="programslot",
+            name="is_active",
         ),
     ]
diff --git a/program/migrations/0012_auto_20180104_0005.py b/program/migrations/0012_auto_20180104_0005.py
index dac9db486934a247a407833cc4ce8114e6bde03b..b3a7011186d162ce4e5422870451b857c565fc04 100644
--- a/program/migrations/0012_auto_20180104_0005.py
+++ b/program/migrations/0012_auto_20180104_0005.py
@@ -12,429 +12,836 @@ class Migration(migrations.Migration):
 
     dependencies = [
         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('program', '0011_programslot_remove_is_active'),
+        ("program", "0011_programslot_remove_is_active"),
     ]
 
     operations = [
         migrations.CreateModel(
-            name='Category',
+            name="Category",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('category', models.CharField(max_length=32, verbose_name='Category')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('color', models.TextField(blank=True, max_length=7, verbose_name='Color')),
-                ('description', models.TextField(blank=True, verbose_name='Description')),
-                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
-                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
-                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("category", models.CharField(max_length=32, verbose_name="Category")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "color",
+                    models.TextField(blank=True, max_length=7, verbose_name="Color"),
+                ),
+                (
+                    "description",
+                    models.TextField(blank=True, verbose_name="Description"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image",
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image (hover)",
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Big button image",
+                    ),
+                ),
             ],
             options={
-                'verbose_name': 'Category',
-                'verbose_name_plural': 'Categories',
-                'ordering': ('category',),
+                "verbose_name": "Category",
+                "verbose_name_plural": "Categories",
+                "ordering": ("category",),
             },
         ),
         migrations.CreateModel(
-            name='Language',
+            name="Language",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=32, verbose_name='Language')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=32, verbose_name="Language")),
             ],
             options={
-                'verbose_name': 'Language',
-                'verbose_name_plural': 'Languages',
-                'ordering': ('language',),
+                "verbose_name": "Language",
+                "verbose_name_plural": "Languages",
+                "ordering": ("language",),
             },
         ),
         migrations.CreateModel(
-            name='RTRCategory',
+            name="RTRCategory",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('rtrcategory', models.CharField(max_length=32, verbose_name='RTR Category')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "rtrcategory",
+                    models.CharField(max_length=32, verbose_name="RTR Category"),
+                ),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
             ],
             options={
-                'verbose_name': 'RTR Category',
-                'verbose_name_plural': 'RTR Categories',
-                'ordering': ('rtrcategory',),
+                "verbose_name": "RTR Category",
+                "verbose_name_plural": "RTR Categories",
+                "ordering": ("rtrcategory",),
             },
         ),
         migrations.CreateModel(
-            name='Schedule',
+            name="Schedule",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('byweekday', models.IntegerField(choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')], verbose_name='Weekday')),
-                ('dstart', models.DateField(verbose_name='First date')),
-                ('tstart', models.TimeField(verbose_name='Start time')),
-                ('tend', models.TimeField(verbose_name='End time')),
-                ('until', models.DateField(verbose_name='Last date')),
-                ('is_repetition', models.BooleanField(default=False, verbose_name='Is repetition')),
-                ('fallback_id', models.IntegerField(blank=True, null=True, verbose_name='Fallback ID')),
-                ('automation_id', models.IntegerField(blank=True, null=True, verbose_name='Automation ID')),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "byweekday",
+                    models.IntegerField(
+                        choices=[
+                            (0, "Monday"),
+                            (1, "Tuesday"),
+                            (2, "Wednesday"),
+                            (3, "Thursday"),
+                            (4, "Friday"),
+                            (5, "Saturday"),
+                            (6, "Sunday"),
+                        ],
+                        verbose_name="Weekday",
+                    ),
+                ),
+                ("dstart", models.DateField(verbose_name="First date")),
+                ("tstart", models.TimeField(verbose_name="Start time")),
+                ("tend", models.TimeField(verbose_name="End time")),
+                ("until", models.DateField(verbose_name="Last date")),
+                (
+                    "is_repetition",
+                    models.BooleanField(default=False, verbose_name="Is repetition"),
+                ),
+                (
+                    "fallback_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Fallback ID"
+                    ),
+                ),
+                (
+                    "automation_id",
+                    models.IntegerField(
+                        blank=True, null=True, verbose_name="Automation ID"
+                    ),
+                ),
+                ("created", models.DateTimeField(auto_now_add=True, null=True)),
+                ("last_updated", models.DateTimeField(auto_now=True, null=True)),
             ],
             options={
-                'verbose_name': 'Schedule',
-                'verbose_name_plural': 'Schedules',
-                'ordering': ('dstart', 'tstart'),
+                "verbose_name": "Schedule",
+                "verbose_name_plural": "Schedules",
+                "ordering": ("dstart", "tstart"),
             },
         ),
         migrations.CreateModel(
-            name='Topic',
+            name="Topic",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('topic', models.CharField(max_length=32, verbose_name='Topic')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image')),
-                ('button_hover', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)')),
-                ('big_button', models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("topic", models.CharField(max_length=32, verbose_name="Topic")),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image",
+                    ),
+                ),
+                (
+                    "button_hover",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Button image (hover)",
+                    ),
+                ),
+                (
+                    "big_button",
+                    models.ImageField(
+                        blank=True,
+                        null=True,
+                        upload_to="buttons",
+                        verbose_name="Big button image",
+                    ),
+                ),
             ],
             options={
-                'verbose_name': 'Topic',
-                'verbose_name_plural': 'Topics',
-                'ordering': ('topic',),
+                "verbose_name": "Topic",
+                "verbose_name_plural": "Topics",
+                "ordering": ("topic",),
             },
         ),
         migrations.CreateModel(
-            name='Type',
+            name="Type",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('type', models.CharField(max_length=32, verbose_name='Type')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('color', models.CharField(default='#ffffff', max_length=7, verbose_name='Color')),
-                ('text_color', models.CharField(default='#000000', max_length=7, verbose_name='Text color')),
-                ('enabled', models.BooleanField(default=True, verbose_name='Enabled')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("type", models.CharField(max_length=32, verbose_name="Type")),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "color",
+                    models.CharField(
+                        default="#ffffff", max_length=7, verbose_name="Color"
+                    ),
+                ),
+                (
+                    "text_color",
+                    models.CharField(
+                        default="#000000", max_length=7, verbose_name="Text color"
+                    ),
+                ),
+                ("enabled", models.BooleanField(default=True, verbose_name="Enabled")),
             ],
             options={
-                'verbose_name': 'Type',
-                'verbose_name_plural': 'Types',
-                'ordering': ('type',),
+                "verbose_name": "Type",
+                "verbose_name_plural": "Types",
+                "ordering": ("type",),
             },
         ),
         migrations.AlterUniqueTogether(
-            name='programslot',
+            name="programslot",
             unique_together=set([]),
         ),
         migrations.RemoveField(
-            model_name='programslot',
-            name='rrule',
+            model_name="programslot",
+            name="rrule",
         ),
         migrations.RemoveField(
-            model_name='programslot',
-            name='show',
+            model_name="programslot",
+            name="show",
         ),
         migrations.AlterModelOptions(
-            name='rrule',
-            options={'ordering': ('pk',), 'verbose_name': 'Recurrence rule', 'verbose_name_plural': 'Recurrence rules'},
+            name="rrule",
+            options={
+                "ordering": ("pk",),
+                "verbose_name": "Recurrence rule",
+                "verbose_name_plural": "Recurrence rules",
+            },
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='broadcastformat',
+            model_name="show",
+            name="broadcastformat",
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='image_enabled',
+            model_name="show",
+            name="image_enabled",
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='showinformation',
+            model_name="show",
+            name="showinformation",
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='showtopic',
+            model_name="show",
+            name="showtopic",
         ),
         migrations.RemoveField(
-            model_name='timeslot',
-            name='programslot',
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='biography',
-            field=models.TextField(blank=True, help_text='Describe yourself and your fields of interest in a few sentences.', null=True, verbose_name='Biography'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='cba_url',
-            field=models.URLField(blank=True, help_text='URL to your CBA profile.', verbose_name='CBA URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='dorftv_url',
-            field=models.URLField(blank=True, help_text='URL to your dorfTV channel.', verbose_name='DorfTV URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='facebook_url',
-            field=models.URLField(blank=True, help_text='URL to your Facebook profile.', verbose_name='Facebook URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='googleplus_url',
-            field=models.URLField(blank=True, help_text='URL to your Google+ profile.', verbose_name='Google+ URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='height',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload a picture of yourself. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='host_images', verbose_name='Profile picture', width_field='width'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='linkedin_url',
-            field=models.URLField(blank=True, help_text='URL to your LinkedIn profile.', verbose_name='LinkedIn URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='twitter_url',
-            field=models.URLField(blank=True, help_text='URL to your Twitter profile.', verbose_name='Twitter URL'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='width',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width'),
-        ),
-        migrations.AddField(
-            model_name='host',
-            name='youtube_url',
-            field=models.URLField(blank=True, help_text='URL to your Youtube channel.', verbose_name='Youtube URL'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='audio_url',
-            field=models.TextField(blank=True, editable=False, verbose_name='Direct URL to a linked audio file'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='cba_id',
-            field=models.IntegerField(blank=True, help_text="Link the note to a certain CBA post by giving its ID. (E.g. if your post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)", null=True, verbose_name='CBA ID'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='height',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='host',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hosts', to='program.Host'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='note_images', verbose_name='Featured image', width_field='width'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI'),
-        ),
-        migrations.AddField(
-            model_name='note',
-            name='slug',
-            field=models.SlugField(default=1, help_text='A simple to read URL for your show.', max_length=32, unique=True, verbose_name='Slug'),
+            model_name="timeslot",
+            name="programslot",
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="biography",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe yourself and your fields of interest in a few sentences.",
+                null=True,
+                verbose_name="Biography",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="cba_url",
+            field=models.URLField(
+                blank=True, help_text="URL to your CBA profile.", verbose_name="CBA URL"
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="dorftv_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your dorfTV channel.",
+                verbose_name="DorfTV URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="facebook_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Facebook profile.",
+                verbose_name="Facebook URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="googleplus_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Google+ profile.",
+                verbose_name="Google+ URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="height",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Height"
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                help_text="Upload a picture of yourself. Images are automatically cropped around"
+                          " the 'Primary Point of Interest'. Click in the image to change it and"
+                          " press Save.",
+                null=True,
+                upload_to="host_images",
+                verbose_name="Profile picture",
+                width_field="width",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="linkedin_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your LinkedIn profile.",
+                verbose_name="LinkedIn URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5",
+                editable=False,
+                max_length=20,
+                verbose_name="Image PPOI",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="twitter_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Twitter profile.",
+                verbose_name="Twitter URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="width",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Width"
+            ),
+        ),
+        migrations.AddField(
+            model_name="host",
+            name="youtube_url",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your Youtube channel.",
+                verbose_name="Youtube URL",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="audio_url",
+            field=models.TextField(
+                blank=True,
+                editable=False,
+                verbose_name="Direct URL to a linked audio file",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="cba_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="Link the note to a certain CBA post by giving its ID. (E.g. if your"
+                          " post's CBA URL is https://cba.fro.at/1234, then your CBA ID is 1234)",
+                null=True,
+                verbose_name="CBA ID",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="height",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Height"
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="host",
+            field=models.ForeignKey(
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="hosts",
+                to="program.Host",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                help_text="Upload an image to your show. Images are automatically cropped around"
+                          " the 'Primary Point of Interest'. Click in the image to change it and"
+                          " press Save.",
+                null=True,
+                upload_to="note_images",
+                verbose_name="Featured image",
+                width_field="width",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5",
+                editable=False,
+                max_length=20,
+                verbose_name="Image PPOI",
+            ),
+        ),
+        migrations.AddField(
+            model_name="note",
+            name="slug",
+            field=models.SlugField(
+                default=1,
+                help_text="A simple to read URL for your show.",
+                max_length=32,
+                unique=True,
+                verbose_name="Slug",
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
-            model_name='note',
-            name='summary',
-            field=models.TextField(blank=True, help_text='Describe your upcoming show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Summary'),
+            model_name="note",
+            name="summary",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe your upcoming show in some sentences. Avoid technical data"
+                          " like airing times and contact information. They will be added"
+                          " automatically.",
+                verbose_name="Summary",
+            ),
         ),
         migrations.AddField(
-            model_name='note',
-            name='user',
-            field=models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='users', to=settings.AUTH_USER_MODEL),
+            model_name="note",
+            name="user",
+            field=models.ForeignKey(
+                default=1,
+                editable=False,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="users",
+                to=settings.AUTH_USER_MODEL,
+            ),
         ),
         migrations.AddField(
-            model_name='note',
-            name='width',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width'),
+            model_name="note",
+            name="width",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Width"
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='cba_series_id',
-            field=models.IntegerField(blank=True, help_text='Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your ID under https://cba.fro.at/series', null=True, verbose_name='CBA Series ID'),
+            model_name="show",
+            name="cba_series_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="Link your show to a CBA series by giving its ID. This will enable CBA"
+                          " upload and will automatically link your show to your CBA archive. Find"
+                          " out your ID under https://cba.fro.at/series",
+                null=True,
+                verbose_name="CBA Series ID",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='fallback_id',
-            field=models.IntegerField(blank=True, null=True, verbose_name='Fallback ID'),
+            model_name="show",
+            name="fallback_id",
+            field=models.IntegerField(
+                blank=True, null=True, verbose_name="Fallback ID"
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='height',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Height'),
+            model_name="show",
+            name="height",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Height"
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='logo',
-            field=models.ImageField(blank=True, null=True, upload_to='show_images', verbose_name='Logo'),
+            model_name="show",
+            name="logo",
+            field=models.ImageField(
+                blank=True, null=True, upload_to="show_images", verbose_name="Logo"
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20, verbose_name='Image PPOI'),
+            model_name="show",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5",
+                editable=False,
+                max_length=20,
+                verbose_name="Image PPOI",
+            ),
         ),
         migrations.AddField(
-            model_name='show',
-            name='width',
-            field=models.PositiveIntegerField(blank=True, editable=False, null=True, verbose_name='Image Width'),
+            model_name="show",
+            name="width",
+            field=models.PositiveIntegerField(
+                blank=True, editable=False, null=True, verbose_name="Image Width"
+            ),
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='is_repetition',
-            field=models.BooleanField(default=False, verbose_name='REP'),
+            model_name="timeslot",
+            name="is_repetition",
+            field=models.BooleanField(default=False, verbose_name="REP"),
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='memo',
-            field=models.TextField(blank=True, verbose_name='Memo'),
+            model_name="timeslot",
+            name="memo",
+            field=models.TextField(blank=True, verbose_name="Memo"),
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='playlist_id',
-            field=models.IntegerField(null=True, verbose_name='Playlist ID'),
+            model_name="timeslot",
+            name="playlist_id",
+            field=models.IntegerField(null=True, verbose_name="Playlist ID"),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='website',
-            field=models.URLField(blank=True, help_text='URL to your personal website.', verbose_name='Website'),
+            model_name="host",
+            name="website",
+            field=models.URLField(
+                blank=True,
+                help_text="URL to your personal website.",
+                verbose_name="Website",
+            ),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='big_button',
-            field=models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Big button image'),
+            model_name="musicfocus",
+            name="big_button",
+            field=models.ImageField(
+                blank=True,
+                null=True,
+                upload_to="buttons",
+                verbose_name="Big button image",
+            ),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='button',
-            field=models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image'),
+            model_name="musicfocus",
+            name="button",
+            field=models.ImageField(
+                blank=True, null=True, upload_to="buttons", verbose_name="Button image"
+            ),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='button_hover',
-            field=models.ImageField(blank=True, null=True, upload_to='buttons', verbose_name='Button image (hover)'),
+            model_name="musicfocus",
+            name="button_hover",
+            field=models.ImageField(
+                blank=True,
+                null=True,
+                upload_to="buttons",
+                verbose_name="Button image (hover)",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='content',
-            field=models.TextField(help_text='Describe your upcoming show in detail.', verbose_name='Content'),
+            model_name="note",
+            name="content",
+            field=models.TextField(
+                help_text="Describe your upcoming show in detail.",
+                verbose_name="Content",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='show',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='program.Show'),
+            model_name="note",
+            name="show",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="notes",
+                to="program.Show",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='title',
-            field=models.CharField(help_text="Give your note a good headline. What will your upcoming show be about? Try to arouse interest to listen to it!<br>Avoid technical data like the show's name, its airing times or its episode number. These data are added automatically.", max_length=128, verbose_name='Title'),
+            model_name="note",
+            name="title",
+            field=models.CharField(
+                help_text="Give your note a good headline. What will your upcoming show be about?"
+                          " Try to arouse interest to listen to it!<br>Avoid technical data like"
+                          " the show's name, its airing times or its episode number. These data"
+                          " are added automatically.",
+                max_length=128,
+                verbose_name="Title",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='description',
-            field=models.TextField(blank=True, help_text='Describe your show in detail.', null=True, verbose_name='Description'),
+            model_name="show",
+            name="description",
+            field=models.TextField(
+                blank=True,
+                help_text="Describe your show in detail.",
+                null=True,
+                verbose_name="Description",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='email',
-            field=models.EmailField(blank=True, help_text='The main contact email address for your show.', max_length=254, null=True, verbose_name='E-Mail'),
+            model_name="show",
+            name="email",
+            field=models.EmailField(
+                blank=True,
+                help_text="The main contact email address for your show.",
+                max_length=254,
+                null=True,
+                verbose_name="E-Mail",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your show. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='show_images', verbose_name='Image', width_field='width'),
+            model_name="show",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                help_text="Upload an image to your show. Images are automatically cropped around"
+                          " the 'Primary Point of Interest'. Click in the image to change it and"
+                          " press Save.",
+                null=True,
+                upload_to="show_images",
+                verbose_name="Image",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='name',
-            field=models.CharField(help_text="The show's name. Avoid a subtitle.", max_length=255, verbose_name='Name'),
+            model_name="show",
+            name="name",
+            field=models.CharField(
+                help_text="The show's name. Avoid a subtitle.",
+                max_length=255,
+                verbose_name="Name",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='short_description',
-            field=models.TextField(help_text='Describe your show in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description'),
+            model_name="show",
+            name="short_description",
+            field=models.TextField(
+                help_text="Describe your show in some sentences. Avoid technical data like airing"
+                          " times and contact information. They will be added automatically.",
+                verbose_name="Short description",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='slug',
-            field=models.CharField(help_text='A simple to read URL for your show', max_length=255, unique=True, verbose_name='Slug'),
+            model_name="show",
+            name="slug",
+            field=models.CharField(
+                help_text="A simple to read URL for your show",
+                max_length=255,
+                unique=True,
+                verbose_name="Slug",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='website',
-            field=models.URLField(blank=True, help_text='Is there a website to your show? Type in its URL.', null=True, verbose_name='Website'),
+            model_name="show",
+            name="website",
+            field=models.URLField(
+                blank=True,
+                help_text="Is there a website to your show? Type in its URL.",
+                null=True,
+                verbose_name="Website",
+            ),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='start',
-            field=models.DateTimeField(verbose_name='Start time'),
+            model_name="timeslot",
+            name="start",
+            field=models.DateTimeField(verbose_name="Start time"),
         ),
         migrations.DeleteModel(
-            name='BroadcastFormat',
+            name="BroadcastFormat",
         ),
         migrations.DeleteModel(
-            name='ProgramSlot',
+            name="ProgramSlot",
         ),
         migrations.DeleteModel(
-            name='ShowInformation',
+            name="ShowInformation",
         ),
         migrations.DeleteModel(
-            name='ShowTopic',
-        ),
-        migrations.AddField(
-            model_name='schedule',
-            name='rrule',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.RRule', verbose_name='Recurrence rule'),
-        ),
-        migrations.AddField(
-            model_name='schedule',
-            name='show',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.Show', verbose_name='Show'),
-        ),
-        migrations.AddField(
-            model_name='show',
-            name='category',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Category', verbose_name='Category'),
-        ),
-        migrations.AddField(
-            model_name='show',
-            name='language',
-            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language', verbose_name='Language'),
-        ),
-        migrations.AddField(
-            model_name='show',
-            name='rtrcategory',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.RTRCategory', verbose_name='RTR Category'),
+            name="ShowTopic",
+        ),
+        migrations.AddField(
+            model_name="schedule",
+            name="rrule",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="schedules",
+                to="program.RRule",
+                verbose_name="Recurrence rule",
+            ),
+        ),
+        migrations.AddField(
+            model_name="schedule",
+            name="show",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="schedules",
+                to="program.Show",
+                verbose_name="Show",
+            ),
+        ),
+        migrations.AddField(
+            model_name="show",
+            name="category",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="shows",
+                to="program.Category",
+                verbose_name="Category",
+            ),
+        ),
+        migrations.AddField(
+            model_name="show",
+            name="language",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="language",
+                to="program.Language",
+                verbose_name="Language",
+            ),
+        ),
+        migrations.AddField(
+            model_name="show",
+            name="rtrcategory",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.RTRCategory",
+                verbose_name="RTR Category",
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
-            model_name='show',
-            name='topic',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Topic', verbose_name='Topic'),
-        ),
-        migrations.AddField(
-            model_name='show',
-            name='type',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.Type', verbose_name='Type'),
+            model_name="show",
+            name="topic",
+            field=models.ManyToManyField(
+                blank=True,
+                related_name="shows",
+                to="program.Topic",
+                verbose_name="Topic",
+            ),
+        ),
+        migrations.AddField(
+            model_name="show",
+            name="type",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.Type",
+                verbose_name="Type",
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
-            model_name='timeslot',
-            name='schedule',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.Schedule', verbose_name='Schedule'),
+            model_name="timeslot",
+            name="schedule",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="timeslots",
+                to="program.Schedule",
+                verbose_name="Schedule",
+            ),
             preserve_default=False,
         ),
     ]
diff --git a/program/migrations/0012_rename_fields.py b/program/migrations/0012_rename_fields.py
index cf4d70ea2023aaf480fd8f505a1e81a4bcc59fdb..7eaebfd7354a140a0b0b1276b504ca2f8edfae6f 100644
--- a/program/migrations/0012_rename_fields.py
+++ b/program/migrations/0012_rename_fields.py
@@ -6,53 +6,73 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0011_link'),
+        ("program", "0011_link"),
     ]
 
     operations = [
         migrations.AlterModelOptions(
-            name='category',
-            options={'ordering': ('name',), 'verbose_name': 'Category', 'verbose_name_plural': 'Categories'},
+            name="category",
+            options={
+                "ordering": ("name",),
+                "verbose_name": "Category",
+                "verbose_name_plural": "Categories",
+            },
         ),
         migrations.AlterModelOptions(
-            name='fundingcategory',
-            options={'ordering': ('name',), 'verbose_name': 'Funding Category', 'verbose_name_plural': 'Funding Categories'},
+            name="fundingcategory",
+            options={
+                "ordering": ("name",),
+                "verbose_name": "Funding Category",
+                "verbose_name_plural": "Funding Categories",
+            },
         ),
         migrations.AlterModelOptions(
-            name='musicfocus',
-            options={'ordering': ('name',), 'verbose_name': 'Music focus', 'verbose_name_plural': 'Music focus'},
+            name="musicfocus",
+            options={
+                "ordering": ("name",),
+                "verbose_name": "Music focus",
+                "verbose_name_plural": "Music focus",
+            },
         ),
         migrations.AlterModelOptions(
-            name='topic',
-            options={'ordering': ('name',), 'verbose_name': 'Topic', 'verbose_name_plural': 'Topics'},
+            name="topic",
+            options={
+                "ordering": ("name",),
+                "verbose_name": "Topic",
+                "verbose_name_plural": "Topics",
+            },
         ),
         migrations.AlterModelOptions(
-            name='type',
-            options={'ordering': ('name',), 'verbose_name': 'Type', 'verbose_name_plural': 'Types'},
+            name="type",
+            options={
+                "ordering": ("name",),
+                "verbose_name": "Type",
+                "verbose_name_plural": "Types",
+            },
         ),
         migrations.RenameField(
-            model_name='category',
-            old_name='category',
-            new_name='name',
+            model_name="category",
+            old_name="category",
+            new_name="name",
         ),
         migrations.RenameField(
-            model_name='fundingcategory',
-            old_name='fundingcategory',
-            new_name='name',
+            model_name="fundingcategory",
+            old_name="fundingcategory",
+            new_name="name",
         ),
         migrations.RenameField(
-            model_name='musicfocus',
-            old_name='focus',
-            new_name='name',
+            model_name="musicfocus",
+            old_name="focus",
+            new_name="name",
         ),
         migrations.RenameField(
-            model_name='topic',
-            old_name='topic',
-            new_name='name',
+            model_name="topic",
+            old_name="topic",
+            new_name="name",
         ),
         migrations.RenameField(
-            model_name='type',
-            old_name='type',
-            new_name='name',
+            model_name="type",
+            old_name="type",
+            new_name="name",
         ),
     ]
diff --git a/program/migrations/0013_auto_20180124_1748.py b/program/migrations/0013_auto_20180124_1748.py
index 5a3ecdffdd22c0079f9b70e78241e8889d93fc49..4be026a3d6a144cf1931a0ed9c3a6c460ffd3127 100644
--- a/program/migrations/0013_auto_20180124_1748.py
+++ b/program/migrations/0013_auto_20180124_1748.py
@@ -8,56 +8,56 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0012_auto_20180104_0005'),
+        ("program", "0012_auto_20180104_0005"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='host',
-            name='is_always_visible',
+            model_name="host",
+            name="is_always_visible",
         ),
         migrations.RemoveField(
-            model_name='type',
-            name='enabled',
+            model_name="type",
+            name="enabled",
         ),
         migrations.AddField(
-            model_name='category',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="category",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='host',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="host",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='language',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="language",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='musicfocus',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="musicfocus",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='rtrcategory',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="rtrcategory",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='topic',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="topic",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AddField(
-            model_name='type',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="type",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='is_repetition',
-            field=models.BooleanField(default=False, verbose_name='(REP)'),
+            model_name="timeslot",
+            name="is_repetition",
+            field=models.BooleanField(default=False, verbose_name="(REP)"),
         ),
     ]
diff --git a/program/migrations/0013_auto_20220221_1637.py b/program/migrations/0013_auto_20220221_1637.py
index 73f259bed0321909a977ed1642eb5cc6d2dd9665..7832adec4a7fe4c44260e91b54048bedd1d440ce 100644
--- a/program/migrations/0013_auto_20220221_1637.py
+++ b/program/migrations/0013_auto_20220221_1637.py
@@ -10,506 +10,572 @@ class Migration(migrations.Migration):
 
     dependencies = [
         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('program', '0012_rename_fields'),
+        ("program", "0012_rename_fields"),
     ]
 
     operations = [
         migrations.AlterModelOptions(
-            name='category',
-            options={'ordering': ('name',)},
+            name="category",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterModelOptions(
-            name='fundingcategory',
-            options={'ordering': ('name',)},
+            name="fundingcategory",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterModelOptions(
-            name='host',
-            options={'ordering': ('name',)},
+            name="host",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterModelOptions(
-            name='language',
-            options={'ordering': ('language',)},
+            name="language",
+            options={"ordering": ("language",)},
         ),
         migrations.AlterModelOptions(
-            name='musicfocus',
-            options={'ordering': ('name',)},
+            name="musicfocus",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterModelOptions(
-            name='note',
-            options={'ordering': ('timeslot',)},
+            name="note",
+            options={"ordering": ("timeslot",)},
         ),
         migrations.AlterModelOptions(
-            name='rrule',
-            options={'ordering': ('pk',)},
+            name="rrule",
+            options={"ordering": ("pk",)},
         ),
         migrations.AlterModelOptions(
-            name='schedule',
-            options={'ordering': ('dstart', 'tstart')},
+            name="schedule",
+            options={"ordering": ("dstart", "tstart")},
         ),
         migrations.AlterModelOptions(
-            name='show',
-            options={'ordering': ('slug',)},
+            name="show",
+            options={"ordering": ("slug",)},
         ),
         migrations.AlterModelOptions(
-            name='timeslot',
-            options={'ordering': ('start', 'end')},
+            name="timeslot",
+            options={"ordering": ("start", "end")},
         ),
         migrations.AlterModelOptions(
-            name='topic',
-            options={'ordering': ('name',)},
+            name="topic",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterModelOptions(
-            name='type',
-            options={'ordering': ('name',)},
+            name="type",
+            options={"ordering": ("name",)},
         ),
         migrations.AlterField(
-            model_name='category',
-            name='abbrev',
+            model_name="category",
+            name="abbrev",
             field=models.CharField(max_length=4, unique=True),
         ),
         migrations.AlterField(
-            model_name='category',
-            name='description',
+            model_name="category",
+            name="description",
             field=models.TextField(blank=True),
         ),
         migrations.AlterField(
-            model_name='category',
-            name='is_active',
+            model_name="category",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='category',
-            name='name',
+            model_name="category",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='category',
-            name='slug',
+            model_name="category",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='fundingcategory',
-            name='abbrev',
+            model_name="fundingcategory",
+            name="abbrev",
             field=models.CharField(max_length=4, unique=True),
         ),
         migrations.AlterField(
-            model_name='fundingcategory',
-            name='is_active',
+            model_name="fundingcategory",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='fundingcategory',
-            name='name',
+            model_name="fundingcategory",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='fundingcategory',
-            name='slug',
+            model_name="fundingcategory",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='biography',
+            model_name="host",
+            name="biography",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='email',
+            model_name="host",
+            name="email",
             field=models.EmailField(blank=True, max_length=254),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='height',
+            model_name="host",
+            name="height",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='host_images', width_field='width'),
+            model_name="host",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="host_images",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='is_active',
+            model_name="host",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='name',
+            model_name="host",
+            name="name",
             field=models.CharField(max_length=128),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20),
+            model_name="host",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5", editable=False, max_length=20
+            ),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='website',
+            model_name="host",
+            name="website",
             field=models.URLField(blank=True),
         ),
         migrations.AlterField(
-            model_name='host',
-            name='width',
+            model_name="host",
+            name="width",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='language',
-            name='is_active',
+            model_name="language",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='language',
-            name='name',
+            model_name="language",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='abbrev',
+            model_name="musicfocus",
+            name="abbrev",
             field=models.CharField(max_length=4, unique=True),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='is_active',
+            model_name="musicfocus",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='name',
+            model_name="musicfocus",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='musicfocus',
-            name='slug',
+            model_name="musicfocus",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='audio_url',
+            model_name="note",
+            name="audio_url",
             field=models.TextField(blank=True, editable=False),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='cba_id',
+            model_name="note",
+            name="cba_id",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='content',
+            model_name="note",
+            name="content",
             field=models.TextField(),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='height',
+            model_name="note",
+            name="height",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='note_images', width_field='width'),
+            model_name="note",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="note_images",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20),
+            model_name="note",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5", editable=False, max_length=20
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='slug',
+            model_name="note",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='status',
+            model_name="note",
+            name="status",
             field=models.IntegerField(default=1),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='summary',
+            model_name="note",
+            name="summary",
             field=models.TextField(blank=True),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='timeslot',
-            field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='program.timeslot'),
+            model_name="note",
+            name="timeslot",
+            field=models.OneToOneField(
+                on_delete=django.db.models.deletion.CASCADE, to="program.timeslot"
+            ),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='title',
+            model_name="note",
+            name="title",
             field=models.CharField(max_length=128),
         ),
         migrations.AlterField(
-            model_name='note',
-            name='width',
+            model_name="note",
+            name="width",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='rrule',
-            name='bysetpos',
+            model_name="rrule",
+            name="bysetpos",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='rrule',
-            name='count',
+            model_name="rrule",
+            name="count",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='rrule',
-            name='freq',
+            model_name="rrule",
+            name="freq",
             field=models.IntegerField(),
         ),
         migrations.AlterField(
-            model_name='rrule',
-            name='interval',
+            model_name="rrule",
+            name="interval",
             field=models.IntegerField(default=1),
         ),
         migrations.AlterField(
-            model_name='rrule',
-            name='name',
+            model_name="rrule",
+            name="name",
             field=models.CharField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='add_business_days_only',
+            model_name="schedule",
+            name="add_business_days_only",
             field=models.BooleanField(default=False),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='add_days_no',
+            model_name="schedule",
+            name="add_days_no",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='byweekday',
+            model_name="schedule",
+            name="byweekday",
             field=models.IntegerField(),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='default_playlist_id',
+            model_name="schedule",
+            name="default_playlist_id",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='dstart',
+            model_name="schedule",
+            name="dstart",
             field=models.DateField(),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='is_repetition',
+            model_name="schedule",
+            name="is_repetition",
             field=models.BooleanField(default=False),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='rrule',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.rrule'),
+            model_name="schedule",
+            name="rrule",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="schedules",
+                to="program.rrule",
+            ),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='show',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='program.show'),
+            model_name="schedule",
+            name="show",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="schedules",
+                to="program.show",
+            ),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='tend',
+            model_name="schedule",
+            name="tend",
             field=models.TimeField(),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='tstart',
+            model_name="schedule",
+            name="tstart",
             field=models.TimeField(),
         ),
         migrations.AlterField(
-            model_name='schedule',
-            name='until',
+            model_name="schedule",
+            name="until",
             field=models.DateField(),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='category',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Category'),
+            model_name="show",
+            name="category",
+            field=models.ManyToManyField(
+                blank=True, related_name="shows", to="program.Category"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='cba_series_id',
+            model_name="show",
+            name="cba_series_id",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='default_playlist_id',
+            model_name="show",
+            name="default_playlist_id",
             field=models.IntegerField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='description',
+            model_name="show",
+            name="description",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='email',
+            model_name="show",
+            name="email",
             field=models.EmailField(blank=True, max_length=254, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='fundingcategory',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.fundingcategory'),
+            model_name="show",
+            name="fundingcategory",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.fundingcategory",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='height',
+            model_name="show",
+            name="height",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='hosts',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Host'),
+            model_name="show",
+            name="hosts",
+            field=models.ManyToManyField(
+                blank=True, related_name="shows", to="program.Host"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', null=True, upload_to='show_images', width_field='width'),
+            model_name="show",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                null=True,
+                upload_to="show_images",
+                width_field="width",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='is_active',
+            model_name="show",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='is_public',
+            model_name="show",
+            name="is_public",
             field=models.BooleanField(default=False),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='language',
-            field=models.ManyToManyField(blank=True, related_name='language', to='program.Language'),
+            model_name="show",
+            name="language",
+            field=models.ManyToManyField(
+                blank=True, related_name="language", to="program.Language"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='logo',
-            field=models.ImageField(blank=True, null=True, upload_to='show_images'),
+            model_name="show",
+            name="logo",
+            field=models.ImageField(blank=True, null=True, upload_to="show_images"),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='musicfocus',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.MusicFocus'),
+            model_name="show",
+            name="musicfocus",
+            field=models.ManyToManyField(
+                blank=True, related_name="shows", to="program.MusicFocus"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='name',
+            model_name="show",
+            name="name",
             field=models.CharField(max_length=255),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='owners',
-            field=models.ManyToManyField(blank=True, related_name='shows', to=settings.AUTH_USER_MODEL),
+            model_name="show",
+            name="owners",
+            field=models.ManyToManyField(
+                blank=True, related_name="shows", to=settings.AUTH_USER_MODEL
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='ppoi',
-            field=versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20),
+            model_name="show",
+            name="ppoi",
+            field=versatileimagefield.fields.PPOIField(
+                default="0.5x0.5", editable=False, max_length=20
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='predecessor',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='successors', to='program.show'),
+            model_name="show",
+            name="predecessor",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="successors",
+                to="program.show",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='short_description',
+            model_name="show",
+            name="short_description",
             field=models.TextField(),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='slug',
+            model_name="show",
+            name="slug",
             field=models.CharField(max_length=255, unique=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='topic',
-            field=models.ManyToManyField(blank=True, related_name='shows', to='program.Topic'),
+            model_name="show",
+            name="topic",
+            field=models.ManyToManyField(
+                blank=True, related_name="shows", to="program.Topic"
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='type',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.type'),
+            model_name="show",
+            name="type",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.type",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='website',
+            model_name="show",
+            name="website",
             field=models.URLField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='width',
+            model_name="show",
+            name="width",
             field=models.PositiveIntegerField(blank=True, editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='end',
+            model_name="timeslot",
+            name="end",
             field=models.DateTimeField(),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='is_repetition',
+            model_name="timeslot",
+            name="is_repetition",
             field=models.BooleanField(default=False),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='memo',
+            model_name="timeslot",
+            name="memo",
             field=models.TextField(blank=True),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='note_id',
+            model_name="timeslot",
+            name="note_id",
             field=models.IntegerField(editable=False, null=True),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='playlist_id',
+            model_name="timeslot",
+            name="playlist_id",
             field=models.IntegerField(null=True),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='schedule',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='timeslots', to='program.schedule'),
+            model_name="timeslot",
+            name="schedule",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="timeslots",
+                to="program.schedule",
+            ),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='start',
+            model_name="timeslot",
+            name="start",
             field=models.DateTimeField(),
         ),
         migrations.AlterField(
-            model_name='topic',
-            name='abbrev',
+            model_name="topic",
+            name="abbrev",
             field=models.CharField(max_length=4, unique=True),
         ),
         migrations.AlterField(
-            model_name='topic',
-            name='is_active',
+            model_name="topic",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='topic',
-            name='name',
+            model_name="topic",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='topic',
-            name='slug',
+            model_name="topic",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
         migrations.AlterField(
-            model_name='type',
-            name='is_active',
+            model_name="type",
+            name="is_active",
             field=models.BooleanField(default=True),
         ),
         migrations.AlterField(
-            model_name='type',
-            name='name',
+            model_name="type",
+            name="name",
             field=models.CharField(max_length=32),
         ),
         migrations.AlterField(
-            model_name='type',
-            name='slug',
+            model_name="type",
+            name="slug",
             field=models.SlugField(max_length=32, unique=True),
         ),
     ]
diff --git a/program/migrations/0014_auto_20180216_2000.py b/program/migrations/0014_auto_20180216_2000.py
index 2f0fc980d018e2e77f24a335543eb7771b1e8be5..787fbf708a334577661bfbca7bdf6b13e4537fb8 100644
--- a/program/migrations/0014_auto_20180216_2000.py
+++ b/program/migrations/0014_auto_20180216_2000.py
@@ -9,36 +9,64 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0013_auto_20180124_1748'),
+        ("program", "0013_auto_20180124_1748"),
     ]
 
     operations = [
         migrations.CreateModel(
-            name='FundingCategory',
+            name="FundingCategory",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('fundingcategory', models.CharField(max_length=32, verbose_name='Funding Category')),
-                ('abbrev', models.CharField(max_length=4, unique=True, verbose_name='Abbreviation')),
-                ('slug', models.SlugField(max_length=32, unique=True, verbose_name='Slug')),
-                ('is_active', models.BooleanField(default=True, verbose_name='Is active?')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "fundingcategory",
+                    models.CharField(max_length=32, verbose_name="Funding Category"),
+                ),
+                (
+                    "abbrev",
+                    models.CharField(
+                        max_length=4, unique=True, verbose_name="Abbreviation"
+                    ),
+                ),
+                (
+                    "slug",
+                    models.SlugField(max_length=32, unique=True, verbose_name="Slug"),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(default=True, verbose_name="Is active?"),
+                ),
             ],
             options={
-                'verbose_name': 'Funding Category',
-                'verbose_name_plural': 'Funding Categories',
-                'ordering': ('fundingcategory',),
+                "verbose_name": "Funding Category",
+                "verbose_name_plural": "Funding Categories",
+                "ordering": ("fundingcategory",),
             },
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='rtrcategory',
+            model_name="show",
+            name="rtrcategory",
         ),
         migrations.DeleteModel(
-            name='RTRCategory',
+            name="RTRCategory",
         ),
         migrations.AddField(
-            model_name='show',
-            name='fundingcategory',
-            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.FundingCategory', verbose_name='Funding Category'),
+            model_name="show",
+            name="fundingcategory",
+            field=models.ForeignKey(
+                default=1,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.FundingCategory",
+                verbose_name="Funding Category",
+            ),
             preserve_default=False,
         ),
     ]
diff --git a/program/migrations/0014_auto_20220221_1641.py b/program/migrations/0014_auto_20220221_1641.py
index b110c96aedfda6dff2ccb5c4d202421f8b82f5d4..602cc4925c134a18614f5208d1366ad3cd62e565 100644
--- a/program/migrations/0014_auto_20220221_1641.py
+++ b/program/migrations/0014_auto_20220221_1641.py
@@ -6,32 +6,32 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0013_auto_20220221_1637'),
+        ("program", "0013_auto_20220221_1637"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='note',
-            name='created',
+            model_name="note",
+            name="created",
         ),
         migrations.RemoveField(
-            model_name='note',
-            name='last_updated',
+            model_name="note",
+            name="last_updated",
         ),
         migrations.RemoveField(
-            model_name='schedule',
-            name='created',
+            model_name="schedule",
+            name="created",
         ),
         migrations.RemoveField(
-            model_name='schedule',
-            name='last_updated',
+            model_name="schedule",
+            name="last_updated",
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='created',
+            model_name="show",
+            name="created",
         ),
         migrations.RemoveField(
-            model_name='show',
-            name='last_updated',
+            model_name="show",
+            name="last_updated",
         ),
     ]
diff --git a/program/migrations/0015_auto_20180218_1111.py b/program/migrations/0015_auto_20180218_1111.py
index 291a19edbbf34a7c51bd15f6dfc4e677f3ed99b9..e0dacaee2d4b3ad78dee05b3247c22933d7dacaa 100644
--- a/program/migrations/0015_auto_20180218_1111.py
+++ b/program/migrations/0015_auto_20180218_1111.py
@@ -8,18 +8,20 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0014_auto_20180216_2000'),
+        ("program", "0014_auto_20180216_2000"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='timeslot',
-            name='note_id',
-            field=models.IntegerField(editable=False, null=True, verbose_name='Note ID'),
+            model_name="timeslot",
+            name="note_id",
+            field=models.IntegerField(
+                editable=False, null=True, verbose_name="Note ID"
+            ),
         ),
         migrations.AlterField(
-            model_name='timeslot',
-            name='is_repetition',
-            field=models.BooleanField(default=False, verbose_name='Is repetition?'),
+            model_name="timeslot",
+            name="is_repetition",
+            field=models.BooleanField(default=False, verbose_name="Is repetition?"),
         ),
     ]
diff --git a/program/migrations/0015_rename_bysetpos_rrule_by_set_pos.py b/program/migrations/0015_rename_bysetpos_rrule_by_set_pos.py
index cded49ca5127c7b826960012aa9c811a15eff0ab..135e8b7d7fe9c7cdff3f5d57dc30e5f884a6a47f 100644
--- a/program/migrations/0015_rename_bysetpos_rrule_by_set_pos.py
+++ b/program/migrations/0015_rename_bysetpos_rrule_by_set_pos.py
@@ -6,13 +6,13 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0014_auto_20220221_1641'),
+        ("program", "0014_auto_20220221_1641"),
     ]
 
     operations = [
         migrations.RenameField(
-            model_name='rrule',
-            old_name='bysetpos',
-            new_name='by_set_pos',
+            model_name="rrule",
+            old_name="bysetpos",
+            new_name="by_set_pos",
         ),
     ]
diff --git a/program/migrations/0016_auto_20180222_1253.py b/program/migrations/0016_auto_20180222_1253.py
index d9cb5da4d6bfcffb80a0f49e3b09b0965c1d1234..a62ca8d15f4b013b2aebfac189652083682e7b4c 100644
--- a/program/migrations/0016_auto_20180222_1253.py
+++ b/program/migrations/0016_auto_20180222_1253.py
@@ -9,13 +9,23 @@ import versatileimagefield.fields
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0015_auto_20180218_1111'),
+        ("program", "0015_auto_20180218_1111"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='note',
-            name='image',
-            field=versatileimagefield.fields.VersatileImageField(blank=True, height_field='height', help_text="Upload an image to your note. Images are automatically cropped around the 'Primary Point of Interest'. Click in the image to change it and press Save.", null=True, upload_to='note_images', verbose_name='Featured image', width_field='width'),
+            model_name="note",
+            name="image",
+            field=versatileimagefield.fields.VersatileImageField(
+                blank=True,
+                height_field="height",
+                help_text="Upload an image to your note. Images are automatically cropped around"
+                          " the 'Primary Point of Interest'. Click in the image to change it and"
+                          " press Save.",
+                null=True,
+                upload_to="note_images",
+                verbose_name="Featured image",
+                width_field="width",
+            ),
         ),
     ]
diff --git a/program/migrations/0016_auto_20220222_0209.py b/program/migrations/0016_auto_20220222_0209.py
index 84ca864ed749ed69c6bf735189e7aa904703e0f6..6fe057f20d27573602c8ae99b88116d79ab0a618 100644
--- a/program/migrations/0016_auto_20220222_0209.py
+++ b/program/migrations/0016_auto_20220222_0209.py
@@ -6,18 +6,18 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0015_rename_bysetpos_rrule_by_set_pos'),
+        ("program", "0015_rename_bysetpos_rrule_by_set_pos"),
     ]
 
     operations = [
         migrations.RenameField(
-            model_name='show',
-            old_name='fundingcategory',
-            new_name='funding_category',
+            model_name="show",
+            old_name="fundingcategory",
+            new_name="funding_category",
         ),
         migrations.RenameField(
-            model_name='show',
-            old_name='musicfocus',
-            new_name='music_focus',
+            model_name="show",
+            old_name="musicfocus",
+            new_name="music_focus",
         ),
     ]
diff --git a/program/migrations/0017_auto_20180314_1409.py b/program/migrations/0017_auto_20180314_1409.py
index 2dc44cba1d9093d7ed457712e8ea6094a15e36b9..e8ca67d96858490ed938c66b71672f417c85fee6 100644
--- a/program/migrations/0017_auto_20180314_1409.py
+++ b/program/migrations/0017_auto_20180314_1409.py
@@ -8,18 +8,20 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0016_auto_20180222_1253'),
+        ("program", "0016_auto_20180222_1253"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='schedule',
-            name='add_business_days_only',
-            field=models.BooleanField(default=False, verbose_name='Only add business days?'),
+            model_name="schedule",
+            name="add_business_days_only",
+            field=models.BooleanField(
+                default=False, verbose_name="Only add business days?"
+            ),
         ),
         migrations.AddField(
-            model_name='schedule',
-            name='add_days_no',
-            field=models.IntegerField(blank=True, null=True, verbose_name='Add days'),
+            model_name="schedule",
+            name="add_days_no",
+            field=models.IntegerField(blank=True, null=True, verbose_name="Add days"),
         ),
     ]
diff --git a/program/migrations/0017_auto_20220302_1711.py b/program/migrations/0017_auto_20220302_1711.py
index 3d49ba5f08416fbcd923a8a39abb84ec8f5d25f8..74634a6ccf93584807741b6ae4026688b3229bed 100644
--- a/program/migrations/0017_auto_20220302_1711.py
+++ b/program/migrations/0017_auto_20220302_1711.py
@@ -6,37 +6,37 @@ from django.db import migrations
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0016_auto_20220222_0209'),
+        ("program", "0016_auto_20220222_0209"),
     ]
 
     operations = [
         migrations.AlterModelOptions(
-            name='schedule',
-            options={'ordering': ('first_date', 'start_time')},
+            name="schedule",
+            options={"ordering": ("first_date", "start_time")},
         ),
         migrations.RenameField(
-            model_name='schedule',
-            old_name='byweekday',
-            new_name='by_weekday',
+            model_name="schedule",
+            old_name="byweekday",
+            new_name="by_weekday",
         ),
         migrations.RenameField(
-            model_name='schedule',
-            old_name='tend',
-            new_name='end_time',
+            model_name="schedule",
+            old_name="tend",
+            new_name="end_time",
         ),
         migrations.RenameField(
-            model_name='schedule',
-            old_name='dstart',
-            new_name='first_date',
+            model_name="schedule",
+            old_name="dstart",
+            new_name="first_date",
         ),
         migrations.RenameField(
-            model_name='schedule',
-            old_name='until',
-            new_name='last_date',
+            model_name="schedule",
+            old_name="until",
+            new_name="last_date",
         ),
         migrations.RenameField(
-            model_name='schedule',
-            old_name='tstart',
-            new_name='start_time',
+            model_name="schedule",
+            old_name="tstart",
+            new_name="start_time",
         ),
     ]
diff --git a/program/migrations/0018_auto_20190810_1146.py b/program/migrations/0018_auto_20190810_1146.py
index 1ed33a09088bd7febb08de51589c1d280b1beef0..4ed3879545d1710f4ad3edc8a21cb4dd8eb76fc1 100644
--- a/program/migrations/0018_auto_20190810_1146.py
+++ b/program/migrations/0018_auto_20190810_1146.py
@@ -8,28 +8,52 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0017_auto_20180314_1409'),
+        ("program", "0017_auto_20180314_1409"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='show',
-            name='cba_series_id',
-            field=models.IntegerField(blank=True, help_text="Link your show to a CBA series by giving its ID. This will enable CBA upload and will automatically link your show to your CBA archive. Find out your show's ID under https://cba.fro.at/series", null=True, verbose_name='CBA Series ID'),
+            model_name="show",
+            name="cba_series_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="Link your show to a CBA series by giving its ID. This will enable CBA"
+                          " upload and will automatically link your show to your CBA archive. Find"
+                          " out your show's ID under https://cba.fro.at/series",
+                null=True,
+                verbose_name="CBA Series ID",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='fallback_id',
-            field=models.IntegerField(blank=True, help_text='If a timeslot of your show is empty, this playlist will be aired as a backup.', null=True, verbose_name='Fallback ID'),
+            model_name="show",
+            name="fallback_id",
+            field=models.IntegerField(
+                blank=True,
+                help_text="If a timeslot of your show is empty, this playlist will be aired as a"
+                          " backup.",
+                null=True,
+                verbose_name="Fallback ID",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='logo',
-            field=models.ImageField(blank=True, help_text='Upload a logo of your show.', null=True, upload_to='show_images', verbose_name='Logo'),
+            model_name="show",
+            name="logo",
+            field=models.ImageField(
+                blank=True,
+                help_text="Upload a logo of your show.",
+                null=True,
+                upload_to="show_images",
+                verbose_name="Logo",
+            ),
         ),
         migrations.AlterField(
-            model_name='show',
-            name='short_description',
-            field=models.TextField(help_text='Describe your show for your listeners in some sentences. Avoid technical data like airing times and contact information. They will be added automatically.', verbose_name='Short description'),
+            model_name="show",
+            name="short_description",
+            field=models.TextField(
+                help_text="Describe your show for your listeners in some sentences. Avoid"
+                          " technical data like airing times and contact information. They will be"
+                          " added automatically.",
+                verbose_name="Short description",
+            ),
         ),
     ]
diff --git a/program/migrations/0019_auto_20190810_1340.py b/program/migrations/0019_auto_20190810_1340.py
index 39e014fd3d493cb8c3131a757d508bb198c2ae5b..f6138a3e82e2413041bdb2f8e2acf2b0a38d2bc1 100644
--- a/program/migrations/0019_auto_20190810_1340.py
+++ b/program/migrations/0019_auto_20190810_1340.py
@@ -9,13 +9,19 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0018_auto_20190810_1146'),
+        ("program", "0018_auto_20190810_1146"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='show',
-            name='fundingcategory',
-            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.FundingCategory', verbose_name='Funding Category'),
+            model_name="show",
+            name="fundingcategory",
+            field=models.ForeignKey(
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.FundingCategory",
+                verbose_name="Funding Category",
+            ),
         ),
     ]
diff --git a/program/migrations/0020_auto_20190810_1341.py b/program/migrations/0020_auto_20190810_1341.py
index b22e98115a21422e1854b06562bf967478ef232c..ad8b2f99382a2627c9040a415ae73079fd840dd6 100644
--- a/program/migrations/0020_auto_20190810_1341.py
+++ b/program/migrations/0020_auto_20190810_1341.py
@@ -9,13 +9,20 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0019_auto_20190810_1340'),
+        ("program", "0019_auto_20190810_1340"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='show',
-            name='fundingcategory',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shows', to='program.FundingCategory', verbose_name='Funding Category'),
+            model_name="show",
+            name="fundingcategory",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="shows",
+                to="program.FundingCategory",
+                verbose_name="Funding Category",
+            ),
         ),
     ]
diff --git a/program/migrations/0021_show_is_active.py b/program/migrations/0021_show_is_active.py
index 8d9d13ad8c84e71c69d54accee09ddd6bc322092..85b7188891a7b4ae733a92051ea57472ae5f4f91 100644
--- a/program/migrations/0021_show_is_active.py
+++ b/program/migrations/0021_show_is_active.py
@@ -8,13 +8,13 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0020_auto_20190810_1341'),
+        ("program", "0020_auto_20190810_1341"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='show',
-            name='is_active',
-            field=models.BooleanField(default=True, verbose_name='Is active?'),
+            model_name="show",
+            name="is_active",
+            field=models.BooleanField(default=True, verbose_name="Is active?"),
         ),
     ]
diff --git a/program/migrations/0022_show_is_public.py b/program/migrations/0022_show_is_public.py
index 51136dd18633f0b41edaf94c37f6f39862f31954..ef05e399ed17b1cdb8c2682a063c68fd2dfbfae2 100644
--- a/program/migrations/0022_show_is_public.py
+++ b/program/migrations/0022_show_is_public.py
@@ -8,13 +8,18 @@ from django.db import migrations, models
 class Migration(migrations.Migration):
 
     dependencies = [
-        ('program', '0021_show_is_active'),
+        ("program", "0021_show_is_active"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='show',
-            name='is_public',
-            field=models.BooleanField(default=False, help_text='Files and Playlists of Public Shows can only be changed by owners but may be used by everyone.', verbose_name='Is Public?'),
+            model_name="show",
+            name="is_public",
+            field=models.BooleanField(
+                default=False,
+                help_text="Files and Playlists of Public Shows can only be changed by owners but"
+                          " may be used by everyone.",
+                verbose_name="Is Public?",
+            ),
         ),
     ]
diff --git a/program/models.py b/program/models.py
index 2525729645ead96f57ba1438be3084b0fb078f6e..3ee04e0d4f2b5a6abfbcac9a53cdf6bebba27cc1 100644
--- a/program/models.py
+++ b/program/models.py
@@ -31,7 +31,11 @@ from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from versatileimagefield.fields import VersatileImageField, PPOIField
 
-from steering.settings import THUMBNAIL_SIZES, AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR, AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE
+from steering.settings import (
+    THUMBNAIL_SIZES,
+    AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR,
+    AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE,
+)
 from program.utils import parse_datetime, parse_date, parse_time
 
 
@@ -41,7 +45,7 @@ class Type(models.Model):
     is_active = models.BooleanField(default=True)
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
 
 class Category(models.Model):
@@ -52,7 +56,7 @@ class Category(models.Model):
     description = models.TextField(blank=True)
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
 
 class Topic(models.Model):
@@ -62,7 +66,7 @@ class Topic(models.Model):
     is_active = models.BooleanField(default=True)
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
 
 class MusicFocus(models.Model):
@@ -72,7 +76,7 @@ class MusicFocus(models.Model):
     is_active = models.BooleanField(default=True)
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
 
 class FundingCategory(models.Model):
@@ -82,7 +86,7 @@ class FundingCategory(models.Model):
     is_active = models.BooleanField(default=True)
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
 
 class Language(models.Model):
@@ -90,7 +94,7 @@ class Language(models.Model):
     is_active = models.BooleanField(default=True)
 
     class Meta:
-        ordering = ('language',)
+        ordering = ("language",)
 
 
 class Host(models.Model):
@@ -102,11 +106,17 @@ class Host(models.Model):
     ppoi = PPOIField()
     height = models.PositiveIntegerField(blank=True, null=True, editable=False)
     width = models.PositiveIntegerField(blank=True, null=True, editable=False)
-    image = VersatileImageField(blank=True, null=True, upload_to='host_images', width_field='width',
-                                height_field='height', ppoi_field='ppoi')
+    image = VersatileImageField(
+        blank=True,
+        null=True,
+        upload_to="host_images",
+        width_field="width",
+        height_field="height",
+        ppoi_field="ppoi",
+    )
 
     class Meta:
-        ordering = ('name',)
+        ordering = ("name",)
 
     def save(self, *args, **kwargs):
         super(Host, self).save(*args, **kwargs)
@@ -118,29 +128,47 @@ class Host(models.Model):
 
 
 class Link(models.Model):
-    host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name='links')
+    host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name="links")
     description = models.CharField(max_length=8)
     url = models.URLField()
 
 
 class Show(models.Model):
-    predecessor = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE, related_name='successors')
-    hosts = models.ManyToManyField(Host, blank=True, related_name='shows')
-    owners = models.ManyToManyField(User, blank=True, related_name='shows')
-    language = models.ManyToManyField(Language, blank=True, related_name='language')
-    type = models.ForeignKey(Type, on_delete=models.CASCADE, related_name='shows')
-    category = models.ManyToManyField(Category, blank=True, related_name='shows')
-    funding_category = models.ForeignKey(FundingCategory, null=True, on_delete=models.CASCADE, blank=True, related_name='shows')
-    topic = models.ManyToManyField(Topic, blank=True, related_name='shows')
-    music_focus = models.ManyToManyField(MusicFocus, blank=True, related_name='shows')
+    predecessor = models.ForeignKey(
+        "self",
+        blank=True,
+        null=True,
+        on_delete=models.CASCADE,
+        related_name="successors",
+    )
+    hosts = models.ManyToManyField(Host, blank=True, related_name="shows")
+    owners = models.ManyToManyField(User, blank=True, related_name="shows")
+    language = models.ManyToManyField(Language, blank=True, related_name="language")
+    type = models.ForeignKey(Type, on_delete=models.CASCADE, related_name="shows")
+    category = models.ManyToManyField(Category, blank=True, related_name="shows")
+    funding_category = models.ForeignKey(
+        FundingCategory,
+        null=True,
+        on_delete=models.CASCADE,
+        blank=True,
+        related_name="shows",
+    )
+    topic = models.ManyToManyField(Topic, blank=True, related_name="shows")
+    music_focus = models.ManyToManyField(MusicFocus, blank=True, related_name="shows")
     name = models.CharField(max_length=255)
     slug = models.CharField(max_length=255, unique=True)
     ppoi = PPOIField()
     height = models.PositiveIntegerField(blank=True, null=True, editable=False)
     width = models.PositiveIntegerField(blank=True, null=True, editable=False)
-    image = VersatileImageField(blank=True, null=True, upload_to='show_images', width_field='width', height_field='height',
-                                ppoi_field='ppoi')
-    logo = models.ImageField(blank=True, null=True, upload_to='show_images')
+    image = VersatileImageField(
+        blank=True,
+        null=True,
+        upload_to="show_images",
+        width_field="width",
+        height_field="height",
+        ppoi_field="ppoi",
+    )
+    logo = models.ImageField(blank=True, null=True, upload_to="show_images")
     short_description = models.TextField()
     description = models.TextField(blank=True, null=True)
     email = models.EmailField(blank=True, null=True)
@@ -151,7 +179,7 @@ class Show(models.Model):
     is_public = models.BooleanField(default=False)
 
     class Meta:
-        ordering = ('slug',)
+        ordering = ("slug",)
 
 
 class RRule(models.Model):
@@ -162,12 +190,12 @@ class RRule(models.Model):
     count = models.IntegerField(blank=True, null=True)
 
     class Meta:
-        ordering = ('pk',)
+        ordering = ("pk",)
 
 
 class Schedule(models.Model):
-    rrule = models.ForeignKey(RRule, on_delete=models.CASCADE, related_name='schedules')
-    show = models.ForeignKey(Show, on_delete=models.CASCADE, related_name='schedules')
+    rrule = models.ForeignKey(RRule, on_delete=models.CASCADE, related_name="schedules")
+    show = models.ForeignKey(Show, on_delete=models.CASCADE, related_name="schedules")
     by_weekday = models.IntegerField()
     first_date = models.DateField()
     start_time = models.TimeField()
@@ -179,50 +207,67 @@ class Schedule(models.Model):
     default_playlist_id = models.IntegerField(blank=True, null=True)
 
     class Meta:
-        ordering = ('first_date', 'start_time')
+        ordering = ("first_date", "start_time")
 
     # FIXME: this does not belong here
     @staticmethod
     def instantiate_upcoming(sdl, show_pk, pk=None):
         """Returns an upcoming schedule instance for conflict resolution"""
         pk = int(pk) if pk is not None else None
-        rrule = RRule.objects.get(pk=int(sdl['rrule']))
+        rrule = RRule.objects.get(pk=int(sdl["rrule"]))
         show = Show.objects.get(pk=int(show_pk))
 
-        is_repetition = True if sdl.get('is_repetition') is True else False
-        default_playlist_id = int(sdl['default_playlist_id']) if sdl.get('default_playlist_id') else None
-        add_days_no = int(sdl['add_days_no']) if sdl.get('add_days_no') else None
-        add_business_days_only = True if sdl.get('add_business_days_only') is True else False
+        is_repetition = True if sdl.get("is_repetition") is True else False
+        default_playlist_id = (
+            int(sdl["default_playlist_id"]) if sdl.get("default_playlist_id") else None
+        )
+        add_days_no = int(sdl["add_days_no"]) if sdl.get("add_days_no") else None
+        add_business_days_only = (
+            True if sdl.get("add_business_days_only") is True else False
+        )
 
         # TODO: replace `dstart` with `first_date` when the dashboard is updated
-        first_date = parse_date(str(sdl['dstart']))
+        first_date = parse_date(str(sdl["dstart"]))
         # TODO: replace `tstart` with `start_time` when the dashboard is updated
-        start_time = sdl['tstart'] + ':00' if len(str(sdl['tstart'])) == 5 else sdl['tstart']
+        start_time = (
+            sdl["tstart"] + ":00" if len(str(sdl["tstart"])) == 5 else sdl["tstart"]
+        )
         # TODO: replace `tend` with `end_time` when the dashboard is updated
-        end_time = sdl['tend'] + ':00' if len(str(sdl['tend'])) == 5 else sdl['tend']
+        end_time = sdl["tend"] + ":00" if len(str(sdl["tend"])) == 5 else sdl["tend"]
 
         start_time = parse_time(str(start_time))
         end_time = parse_time(str(end_time))
 
         # TODO: replace `until` with `last_date` when the dashboard is updated
-        if sdl['until']:
-            last_date = parse_date(str(sdl['until']))
+        if sdl["until"]:
+            last_date = parse_date(str(sdl["until"]))
         else:
             # If no until date was set
             # Set it to the end of the year
             # Or add x days
             if AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR:
                 year = timezone.now().year
-                last_date = parse_date(f'{year}-12-31')
+                last_date = parse_date(f"{year}-12-31")
             else:
-                last_date = first_date + timedelta(days=+AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE)
+                last_date = first_date + timedelta(
+                    days=+AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE
+                )
 
         # TODO: replace `byweekday` with `by_weekday` when the dashboard is updated
-        schedule = Schedule(pk=pk, by_weekday=sdl['byweekday'], rrule=rrule,
-                            first_date=first_date, start_time=start_time, end_time=end_time,
-                            last_date=last_date, is_repetition=is_repetition,
-                            default_playlist_id=default_playlist_id, show=show,
-                            add_days_no=add_days_no, add_business_days_only=add_business_days_only)
+        schedule = Schedule(
+            pk=pk,
+            by_weekday=sdl["byweekday"],
+            rrule=rrule,
+            first_date=first_date,
+            start_time=start_time,
+            end_time=end_time,
+            last_date=last_date,
+            is_repetition=is_repetition,
+            default_playlist_id=default_playlist_id,
+            show=show,
+            add_days_no=add_days_no,
+            add_business_days_only=add_business_days_only,
+        )
 
         return schedule
 
@@ -259,7 +304,9 @@ class Schedule(models.Model):
         elif schedule.rrule.freq == 3 and schedule.rrule.pk == 2:  # Daily timeslots
             by_weekday_start = (0, 1, 2, 3, 4, 5, 6)
             by_weekday_end = (0, 1, 2, 3, 4, 5, 6)
-        elif schedule.rrule.freq == 3 and schedule.rrule.pk == 3:  # Business days MO - FR/SA
+        elif (
+            schedule.rrule.freq == 3 and schedule.rrule.pk == 3
+        ):  # Business days MO - FR/SA
             by_weekday_start = (0, 1, 2, 3, 4)
             if schedule.end_time < schedule.start_time:
                 # End days for over midnight
@@ -289,21 +336,29 @@ class Schedule(models.Model):
             starts.append(datetime.combine(schedule.first_date, schedule.start_time))
             ends.append(datetime.combine(last_date, schedule.end_time))
         else:
-            starts = list(rrule(freq=schedule.rrule.freq,
-                                dtstart=datetime.combine(schedule.first_date, schedule.start_time),
-                                interval=schedule.rrule.interval,
-                                until=schedule.last_date + relativedelta(days=+1),
-                                bysetpos=schedule.rrule.by_set_pos,
-                                byweekday=by_weekday_start,
-                                byweekno=by_week_no))
-
-            ends = list(rrule(freq=schedule.rrule.freq,
-                              dtstart=datetime.combine(last_date, schedule.end_time),
-                              interval=schedule.rrule.interval,
-                              until=schedule.last_date + relativedelta(days=+1),
-                              bysetpos=schedule.rrule.by_set_pos,
-                              byweekday=by_weekday_end,
-                              byweekno=by_week_no_end))
+            starts = list(
+                rrule(
+                    freq=schedule.rrule.freq,
+                    dtstart=datetime.combine(schedule.first_date, schedule.start_time),
+                    interval=schedule.rrule.interval,
+                    until=schedule.last_date + relativedelta(days=+1),
+                    bysetpos=schedule.rrule.by_set_pos,
+                    byweekday=by_weekday_start,
+                    byweekno=by_week_no,
+                )
+            )
+
+            ends = list(
+                rrule(
+                    freq=schedule.rrule.freq,
+                    dtstart=datetime.combine(last_date, schedule.end_time),
+                    interval=schedule.rrule.interval,
+                    until=schedule.last_date + relativedelta(days=+1),
+                    bysetpos=schedule.rrule.by_set_pos,
+                    byweekday=by_weekday_end,
+                    byweekno=by_week_no_end,
+                )
+            )
 
         for k in range(min(len(starts), len(ends))):
 
@@ -312,45 +367,59 @@ class Schedule(models.Model):
             #       produces wrong end dates if the 1st Tuesday is before the 1st Monday
             #       In this case we take the next day instead of rrule's calculated end
             if starts[k] > ends[k]:
-                ends[k] = datetime.combine(starts[k] + relativedelta(days=+1), schedule.end_time)
+                ends[k] = datetime.combine(
+                    starts[k] + relativedelta(days=+1), schedule.end_time
+                )
 
-            '''
+            """
             Add a number of days to the generated dates?
 
             This can be helpful for repetitions:
 
             Examples:
 
-              1. If RRule is "Every 1st Monday" and we want its repetition alyways to be on the following day,
-                 the repetition's RRule is the same but add_days_no is 1
+              1. If RRule is "Every 1st Monday" and we want its repetition alyways to be on the
+                 following day, the repetition's RRule is the same but add_days_no is 1
 
                  If we would set the repetition to "Every 1st Tuesday" instead
                  we will get unmeant results if the 1st Tuesday is before the 1st Monday
                  (e.g. 1st Tue = May 1 2018, 1st Mon = May 7 2018)
 
-              2. If RRule is "Every 1st Friday" and we want its repetition always to be on the following business day,
-                 the repetition's RRule is the same but add_days_no is 1 and add_business_days_only is True
-                 (e.g. original date = Fri, March 2 2018; generated date = Mon, March 5 2018)
+              2. If RRule is "Every 1st Friday" and we want its repetition always to be on the
+                 following business day, the repetition's RRule is the same but add_days_no is 1
+                 and add_business_days_only is True (e.g. original date = Fri, March 2 2018;
+                 generated date = Mon, March 5 2018)
 
             In the UI these can be presets:
                 "On the following day" (add_days_no=1,add_business_days_only=False) or
                 "On the following business day" (add_days_no=1,add_business_days_only=True)
 
-            '''
+            """
             if schedule.add_days_no is not None and schedule.add_days_no > 0:
-                # If only business days and weekday is Fri, Sat or Sun: add add_days_no beginning from Sunday
+                # If only business days and weekday is Fri, Sat or Sun: add add_days_no beginning
+                # from Sunday
                 weekday = datetime.date(starts[k]).weekday()
                 if schedule.add_business_days_only and weekday > 3:
                     days_until_sunday = 6 - weekday
-                    starts[k] = starts[k] + relativedelta(days=+days_until_sunday + schedule.add_days_no)
-                    ends[k] = ends[k] + relativedelta(days=+days_until_sunday + schedule.add_days_no)
+                    starts[k] = starts[k] + relativedelta(
+                        days=+days_until_sunday + schedule.add_days_no
+                    )
+                    ends[k] = ends[k] + relativedelta(
+                        days=+days_until_sunday + schedule.add_days_no
+                    )
                 else:
                     starts[k] = starts[k] + relativedelta(days=+schedule.add_days_no)
                     ends[k] = ends[k] + relativedelta(days=+schedule.add_days_no)
 
                 if ends[k].date() > schedule.last_date:
                     schedule.last_date = ends[k].date()
-            timeslots.append(TimeSlot(schedule=schedule, start=timezone.make_aware(starts[k]), end=timezone.make_aware(ends[k])))
+            timeslots.append(
+                TimeSlot(
+                    schedule=schedule,
+                    start=timezone.make_aware(starts[k]),
+                    end=timezone.make_aware(ends[k]),
+                )
+            )
 
         return timeslots
 
@@ -369,7 +438,9 @@ class Schedule(models.Model):
             collision = TimeSlot.objects.get_colliding_timeslots(ts)
 
             if collision:
-                collisions.append(collision[0])  # TODO: Do we really always retrieve one?
+                collisions.append(
+                    collision[0]
+                )  # TODO: Do we really always retrieve one?
             else:
                 collisions.append(None)
 
@@ -380,7 +451,8 @@ class Schedule(models.Model):
     def generate_conflicts(timeslots):
         """
         Tests a list of timeslot objects for colliding timeslots in the database
-        Returns a list of conflicts containing dicts of projected timeslots, collisions and solutions
+        Returns a list of conflicts containing dicts of projected timeslots, collisions and
+        solutions
         """
 
         conflicts = {}
@@ -389,10 +461,6 @@ class Schedule(models.Model):
 
         # Cycle each timeslot
         for ts in timeslots:
-
-            # Contains one conflict: a projected timeslot, collisions and solutions
-            conflict = {}
-
             # Contains collisions
             collisions = []
 
@@ -400,36 +468,52 @@ class Schedule(models.Model):
             solution_choices = set()
 
             # Get collisions for each timeslot
-            collision_list = list(TimeSlot.objects.get_colliding_timeslots(ts).order_by('start'))
+            collision_list = list(
+                TimeSlot.objects.get_colliding_timeslots(ts).order_by("start")
+            )
 
             # Add the projected timeslot
-            projected_entry = {'hash': ts.hash, 'start': str(ts.start), 'end': str(ts.end)}
+            projected_entry = {
+                "hash": ts.hash,
+                "start": str(ts.start),
+                "end": str(ts.end),
+            }
 
             for c in collision_list:
                 # Add the collision
-                collision = {'id': c.id, 'start': str(c.start), 'end': str(c.end), 'playlist_id': c.playlist_id,
-                             'show': c.show.id, 'show_name': c.show.name, 'is_repetition': c.is_repetition,
-                             'schedule': c.schedule_id, 'memo': c.memo}
+                collision = {
+                    "id": c.id,
+                    "start": str(c.start),
+                    "end": str(c.end),
+                    "playlist_id": c.playlist_id,
+                    "show": c.show.id,
+                    "show_name": c.show.name,
+                    "is_repetition": c.is_repetition,
+                    "schedule": c.schedule_id,
+                    "memo": c.memo,
+                }
 
                 # Get note
                 try:
-                    note = Note.objects.get(timeslot=c.id).values_list('id', flat=True)
-                    collision['note_id'] = note
+                    note = Note.objects.get(timeslot=c.id).values_list("id", flat=True)
+                    collision["note_id"] = note
                 except ObjectDoesNotExist:
                     pass
 
                 collisions.append(collision)
 
-                '''Determine acceptable solutions'''
+                """Determine acceptable solutions"""
 
                 if len(collision_list) > 1:
-                    # If there is more than one collision: Only these two are supported at the moment
-                    solution_choices.add('theirs')
-                    solution_choices.add('ours')
+                    # If there is more than one collision: Only these two are supported at the
+                    # moment
+                    solution_choices.add("theirs")
+                    solution_choices.add("ours")
                 else:
-                    # These two are always possible: Either keep theirs and remove ours or vice versa
-                    solution_choices.add('theirs')
-                    solution_choices.add('ours')
+                    # These two are always possible: Either keep theirs and remove ours or vice
+                    # versa
+                    solution_choices.add("theirs")
+                    solution_choices.add("ours")
 
                     # Partly overlapping: projected starts earlier than existing and ends earlier
                     #
@@ -442,8 +526,8 @@ class Schedule(models.Model):
                     #   +--+
                     #
                     if ts.end > c.start > ts.start <= c.end:
-                        solution_choices.add('theirs-end')
-                        solution_choices.add('ours-end')
+                        solution_choices.add("theirs-end")
+                        solution_choices.add("ours-end")
 
                     # Partly overlapping: projected starts later than existing and ends later
                     #
@@ -456,8 +540,8 @@ class Schedule(models.Model):
                     #        +--+
                     #
                     if c.start <= ts.start < c.end < ts.end:
-                        solution_choices.add('theirs-start')
-                        solution_choices.add('ours-start')
+                        solution_choices.add("theirs-start")
+                        solution_choices.add("ours-start")
 
                     # Fully overlapping: projected starts earlier and ends later than existing
                     #
@@ -469,9 +553,9 @@ class Schedule(models.Model):
                     #        +--+
                     #
                     if ts.start < c.start and ts.end > c.end:
-                        solution_choices.add('theirs-end')
-                        solution_choices.add('theirs-start')
-                        solution_choices.add('theirs-both')
+                        solution_choices.add("theirs-end")
+                        solution_choices.add("theirs-start")
+                        solution_choices.add("theirs-both")
 
                     # Fully overlapping: projected starts later and ends earlier than existing
                     #
@@ -483,21 +567,21 @@ class Schedule(models.Model):
                     #   +--+
                     #
                     if ts.start > c.start and ts.end < c.end:
-                        solution_choices.add('ours-end')
-                        solution_choices.add('ours-start')
-                        solution_choices.add('ours-both')
+                        solution_choices.add("ours-end")
+                        solution_choices.add("ours-start")
+                        solution_choices.add("ours-both")
 
             if len(collisions) > 0:
-                solutions[ts.hash] = ''
+                solutions[ts.hash] = ""
 
-            projected_entry['collisions'] = collisions
-            projected_entry['solution_choices'] = solution_choices
+            projected_entry["collisions"] = collisions
+            projected_entry["solution_choices"] = solution_choices
             projected.append(projected_entry)
 
-        conflicts['projected'] = projected
-        conflicts['solutions'] = solutions
-        conflicts['notes'] = {}
-        conflicts['playlists'] = {}
+        conflicts["projected"] = projected
+        conflicts["solutions"] = solutions
+        conflicts["notes"] = {}
+        conflicts["playlists"] = {}
 
         return conflicts
 
@@ -524,14 +608,18 @@ class Schedule(models.Model):
             existing_schedule = Schedule.objects.get(pk=int(schedule_pk))
 
             if schedule.last_date > existing_schedule.last_date:
-                last_timeslot = TimeSlot.objects.filter(schedule=existing_schedule).order_by('start').reverse()[0]
+                last_timeslot = (
+                    TimeSlot.objects.filter(schedule=existing_schedule)
+                    .order_by("start")
+                    .reverse()[0]
+                )
                 gen_schedule.first_date = last_timeslot.start.date() + timedelta(days=1)
 
         timeslots = Schedule.generate_timeslots(gen_schedule)
 
         # Generate conflicts and add schedule
         conflicts = Schedule.generate_conflicts(timeslots)
-        conflicts['schedule'] = model_to_dict(schedule)
+        conflicts["schedule"] = model_to_dict(schedule)
 
         return conflicts
 
@@ -546,8 +634,8 @@ class Schedule(models.Model):
         Returns an empty list if resolution was successful
         """
 
-        sdl = data['schedule']
-        solutions = data['solutions']
+        sdl = data["schedule"]
+        solutions = data["solutions"]
 
         # Regenerate conflicts
         schedule = Schedule.instantiate_upcoming(sdl, show_pk, schedule_pk)
@@ -555,15 +643,17 @@ class Schedule(models.Model):
         conflicts = Schedule.make_conflicts(sdl, schedule_pk, show_pk)
 
         if schedule.rrule.freq > 0 and schedule.first_date == schedule.last_date:
-            return {'detail': _("Start and until dates mustn't be the same")}
+            return {"detail": _("Start and until dates mustn't be the same")}
 
         if schedule.last_date < schedule.first_date:
-            return {'detail': _("Until date mustn't be before start")}
+            return {"detail": _("Until date mustn't be before start")}
 
-        num_conflicts = len([pr for pr in conflicts['projected'] if len(pr['collisions']) > 0])
+        num_conflicts = len(
+            [pr for pr in conflicts["projected"] if len(pr["collisions"]) > 0]
+        )
 
         if len(solutions) != num_conflicts:
-            return {'detail': _("Numbers of conflicts and solutions don't match.")}
+            return {"detail": _("Numbers of conflicts and solutions don't match.")}
 
         # Projected timeslots to create
         create = []
@@ -577,48 +667,52 @@ class Schedule(models.Model):
         # Error messages
         errors = {}
 
-        for ts in conflicts['projected']:
+        for ts in conflicts["projected"]:
             # If no solution necessary
             #
             #     - Create the projected timeslot and skip
             #
-            if 'solution_choices' not in ts or len(ts['collisions']) < 1:
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], ts['end'], schedule, show)
+            if "solution_choices" not in ts or len(ts["collisions"]) < 1:
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
                 continue
 
             # Check hash (if start, end, rrule or byweekday changed)
-            if not ts['hash'] in solutions:
-                errors[ts['hash']] = _("This change on the timeslot is not allowed.")
+            if not ts["hash"] in solutions:
+                errors[ts["hash"]] = _("This change on the timeslot is not allowed.")
                 continue
 
             # If no resolution given
             #
             #     - Skip
             #
-            if solutions[ts['hash']] == '':
-                errors[ts['hash']] = _("No solution given.")
+            if solutions[ts["hash"]] == "":
+                errors[ts["hash"]] = _("No solution given.")
                 continue
 
             # If resolution is not accepted for this conflict
             #
             #     - Skip
             #
-            if not solutions[ts['hash']] in ts['solution_choices']:
-                errors[ts['hash']] = _("Given solution is not accepted for this conflict.")
+            if not solutions[ts["hash"]] in ts["solution_choices"]:
+                errors[ts["hash"]] = _(
+                    "Given solution is not accepted for this conflict."
+                )
                 continue
 
-            '''Conflict resolution'''
+            """Conflict resolution"""
 
-            existing = ts['collisions'][0]
-            solution = solutions[ts['hash']]
+            existing = ts["collisions"][0]
+            solution = solutions[ts["hash"]]
 
             # theirs
             #
             #     - Discard the projected timeslot
             #     - Keep the existing collision(s)
             #
-            if solution == 'theirs':
+            if solution == "theirs":
                 continue
 
             # ours
@@ -626,14 +720,16 @@ class Schedule(models.Model):
             #     - Create the projected timeslot
             #     - Delete the existing collision(s)
             #
-            if solution == 'ours':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], ts['end'], schedule, show)
+            if solution == "ours":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
                 # Delete collision(s)
-                for ex in ts['collisions']:
+                for ex in ts["collisions"]:
                     try:
-                        existing_ts = TimeSlot.objects.get(pk=ex['id'])
+                        existing_ts = TimeSlot.objects.get(pk=ex["id"])
                         delete.append(existing_ts)
                     except ObjectDoesNotExist:
                         pass
@@ -643,8 +739,10 @@ class Schedule(models.Model):
             #     - Keep the existing timeslot
             #     - Create projected with end of existing start
             #
-            if solution == 'theirs-end':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], existing['start'], schedule, show)
+            if solution == "theirs-end":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], existing["start"], schedule, show
+                )
                 create.append(projected_ts)
 
             # ours-end
@@ -652,12 +750,14 @@ class Schedule(models.Model):
             #     - Create the projected timeslot
             #     - Change the start of the existing collision to projected end
             #
-            if solution == 'ours-end':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], ts['end'], schedule, show)
+            if solution == "ours-end":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
-                existing_ts = TimeSlot.objects.get(pk=existing['id'])
-                existing_ts.start = parse_datetime(ts['end'])
+                existing_ts = TimeSlot.objects.get(pk=existing["id"])
+                existing_ts.start = parse_datetime(ts["end"])
                 update.append(existing_ts)
 
             # theirs-start
@@ -665,8 +765,10 @@ class Schedule(models.Model):
             #     - Keep existing
             #     - Create projected with start time of existing end
             #
-            if solution == 'theirs-start':
-                projected_ts = TimeSlot.objects.instantiate(existing['end'], ts['end'], schedule, show)
+            if solution == "theirs-start":
+                projected_ts = TimeSlot.objects.instantiate(
+                    existing["end"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
             # ours-start
@@ -674,24 +776,31 @@ class Schedule(models.Model):
             #     - Create the projected timeslot
             #     - Change end of existing to projected start
             #
-            if solution == 'ours-start':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], ts['end'], schedule, show)
+            if solution == "ours-start":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
-                existing_ts = TimeSlot.objects.get(pk=existing['id'])
-                existing_ts.end = parse_datetime(ts['start'])
+                existing_ts = TimeSlot.objects.get(pk=existing["id"])
+                existing_ts.end = parse_datetime(ts["start"])
                 update.append(existing_ts)
 
             # theirs-both
             #
             #     - Keep existing
-            #     - Create two projected timeslots with end of existing start and start of existing end
+            #     - Create two projected timeslots with end of existing start and start of existing
+            #       end
             #
-            if solution == 'theirs-both':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], existing['start'], schedule, show)
+            if solution == "theirs-both":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], existing["start"], schedule, show
+                )
                 create.append(projected_ts)
 
-                projected_ts = TimeSlot.objects.instantiate(existing['end'], ts['end'], schedule, show)
+                projected_ts = TimeSlot.objects.instantiate(
+                    existing["end"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
             # ours-both
@@ -701,58 +810,72 @@ class Schedule(models.Model):
             #       - Set existing end time to projected start
             #       - Create another one with start = projected end and end = existing end
             #
-            if solution == 'ours-both':
-                projected_ts = TimeSlot.objects.instantiate(ts['start'], ts['end'], schedule, show)
+            if solution == "ours-both":
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["start"], ts["end"], schedule, show
+                )
                 create.append(projected_ts)
 
-                existing_ts = TimeSlot.objects.get(pk=existing['id'])
-                existing_ts.end = parse_datetime(ts['start'])
+                existing_ts = TimeSlot.objects.get(pk=existing["id"])
+                existing_ts.end = parse_datetime(ts["start"])
                 update.append(existing_ts)
 
-                projected_ts = TimeSlot.objects.instantiate(ts['end'], existing['end'], schedule, show)
+                projected_ts = TimeSlot.objects.instantiate(
+                    ts["end"], existing["end"], schedule, show
+                )
                 create.append(projected_ts)
 
         # If there were any errors, don't make any db changes yet
         # but add error messages and return already chosen solutions
         if len(errors) > 0:
-            conflicts = Schedule.make_conflicts(model_to_dict(schedule), schedule.pk, show.pk)
+            conflicts = Schedule.make_conflicts(
+                model_to_dict(schedule), schedule.pk, show.pk
+            )
 
-            partly_resolved = conflicts['projected']
+            partly_resolved = conflicts["projected"]
             saved_solutions = {}
 
             # Add already chosen resolutions and error message to conflict
-            for index, c in enumerate(conflicts['projected']):
+            for index, c in enumerate(conflicts["projected"]):
 
                 # The element should only exist if there was a collision
-                if len(c['collisions']) > 0:
-                    saved_solutions[c['hash']] = ''
+                if len(c["collisions"]) > 0:
+                    saved_solutions[c["hash"]] = ""
 
-                if c['hash'] in solutions and solutions[c['hash']] in c['solution_choices']:
-                    saved_solutions[c['hash']] = solutions[c['hash']]
+                if (
+                    c["hash"] in solutions
+                    and solutions[c["hash"]] in c["solution_choices"]
+                ):
+                    saved_solutions[c["hash"]] = solutions[c["hash"]]
 
-                if c['hash'] in errors:
-                    partly_resolved[index]['error'] = errors[c['hash']]
+                if c["hash"] in errors:
+                    partly_resolved[index]["error"] = errors[c["hash"]]
 
             # Re-insert post data
-            conflicts['projected'] = partly_resolved
-            conflicts['solutions'] = saved_solutions
-            conflicts['notes'] = data.get('notes')
-            conflicts['playlists'] = data.get('playlists')
+            conflicts["projected"] = partly_resolved
+            conflicts["solutions"] = saved_solutions
+            conflicts["notes"] = data.get("notes")
+            conflicts["playlists"] = data.get("playlists")
 
             return conflicts
 
         # Collect upcoming timeslots to delete which might still remain
-        del_timeslots = TimeSlot.objects.filter(schedule=schedule, start__gt=schedule.last_date)
+        del_timeslots = TimeSlot.objects.filter(
+            schedule=schedule, start__gt=schedule.last_date
+        )
         for del_ts in del_timeslots:
             delete.append(del_ts)
 
         # If 'dryrun' is true, just return the projected changes instead of executing them
-        if 'dryrun' in sdl and sdl['dryrun']:
-            output = {'create': [model_to_dict(ts) for ts in create], 'update': [model_to_dict(ts) for ts in update],
-                      'delete': [model_to_dict(ts) for ts in delete]}
+        if "dryrun" in sdl and sdl["dryrun"]:
+            output = {
+                "create": [model_to_dict(ts) for ts in create],
+                "update": [model_to_dict(ts) for ts in update],
+                "delete": [model_to_dict(ts) for ts in delete],
+            }
             return output
 
-        '''Database changes if no errors found'''
+        """Database changes if no errors found"""
 
         # Only save schedule if timeslots were created
         if create:
@@ -768,15 +891,15 @@ class Schedule(models.Model):
             ts.schedule = schedule
 
             # Reassign playlists
-            if 'playlists' in data and ts.hash in data['playlists']:
-                ts.playlist_id = int(data['playlists'][ts.hash])
+            if "playlists" in data and ts.hash in data["playlists"]:
+                ts.playlist_id = int(data["playlists"][ts.hash])
 
             ts.save()
 
             # Reassign notes
-            if 'notes' in data and ts.hash in data['notes']:
+            if "notes" in data and ts.hash in data["notes"]:
                 try:
-                    note = Note.objects.get(pk=int(data['notes'][ts.hash]))
+                    note = Note.objects.get(pk=int(data["notes"][ts.hash]))
                     note.timeslot_id = ts.id
                     note.save(update_fields=["timeslot_id"])
 
@@ -796,43 +919,54 @@ class Schedule(models.Model):
 class TimeSlotManager(models.Manager):
     @staticmethod
     def instantiate(start, end, schedule, show):
-        return TimeSlot(start=parse_datetime(start),
-                        end=parse_datetime(end),
-                        show=show, is_repetition=schedule.is_repetition, schedule=schedule)
+        return TimeSlot(
+            start=parse_datetime(start),
+            end=parse_datetime(end),
+            show=show,
+            is_repetition=schedule.is_repetition,
+            schedule=schedule,
+        )
 
     @staticmethod
     def get_24h_timeslots(start):
         end = timezone.make_aware(start + timedelta(hours=24))
 
-        return TimeSlot.objects.filter(Q(start__lte=start, end__gte=start) |
-                                       Q(start__gt=start, start__lt=end)).exclude(end=start)
+        return TimeSlot.objects.filter(
+            Q(start__lte=start, end__gte=start) | Q(start__gt=start, start__lt=end)
+        ).exclude(end=start)
 
     @staticmethod
     def get_7d_timeslots(start):
         start = datetime.combine(start, time(0, 0))
         end = timezone.make_aware(start + timedelta(days=7))
 
-        return TimeSlot.objects.filter(Q(start__lte=start, end__gte=start) |
-                                       Q(start__gt=start, start__lt=end)).exclude(end=start)
+        return TimeSlot.objects.filter(
+            Q(start__lte=start, end__gte=start) | Q(start__gt=start, start__lt=end)
+        ).exclude(end=start)
 
     @staticmethod
     def get_timerange_timeslots(start, end):
-        return TimeSlot.objects.filter(Q(start__lte=start, end__gte=start) |
-                                       Q(start__gt=start, start__lt=end)).exclude(end=start)
+        return TimeSlot.objects.filter(
+            Q(start__lte=start, end__gte=start) | Q(start__gt=start, start__lt=end)
+        ).exclude(end=start)
 
     @staticmethod
     def get_colliding_timeslots(timeslot):
         return TimeSlot.objects.filter(
-            (Q(start__lt=timeslot.end) & Q(end__gte=timeslot.end)) |
-            (Q(end__gt=timeslot.start) & Q(end__lte=timeslot.end)) |
-            (Q(start__gte=timeslot.start) & Q(end__lte=timeslot.end)) |
-            (Q(start__lte=timeslot.start) & Q(end__gte=timeslot.end))
+            (Q(start__lt=timeslot.end) & Q(end__gte=timeslot.end))
+            | (Q(end__gt=timeslot.start) & Q(end__lte=timeslot.end))
+            | (Q(start__gte=timeslot.start) & Q(end__lte=timeslot.end))
+            | (Q(start__lte=timeslot.start) & Q(end__gte=timeslot.end))
         )
 
 
 class TimeSlot(models.Model):
-    schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE, related_name='timeslots')
-    show = models.ForeignKey(Show, editable=False, on_delete=models.CASCADE, related_name='timeslots')
+    schedule = models.ForeignKey(
+        Schedule, on_delete=models.CASCADE, related_name="timeslots"
+    )
+    show = models.ForeignKey(
+        Show, editable=False, on_delete=models.CASCADE, related_name="timeslots"
+    )
     start = models.DateTimeField()
     end = models.DateTimeField()
     memo = models.TextField(blank=True)
@@ -843,7 +977,7 @@ class TimeSlot(models.Model):
     objects = TimeSlotManager()
 
     class Meta:
-        ordering = ('start', 'end')
+        ordering = ("start", "end")
 
     def save(self, *args, **kwargs):
         self.show = self.schedule.show
@@ -852,8 +986,13 @@ class TimeSlot(models.Model):
 
     @property
     def hash(self):
-        string = str(self.start) + str(self.end) + str(self.schedule.rrule.id) + str(self.schedule.by_weekday)
-        return str(''.join(s for s in string if s.isdigit()))
+        string = (
+            str(self.start)
+            + str(self.end)
+            + str(self.schedule.rrule.id)
+            + str(self.schedule.by_weekday)
+        )
+        return str("".join(s for s in string if s.isdigit()))
 
 
 class Note(models.Model):
@@ -865,18 +1004,30 @@ class Note(models.Model):
     ppoi = PPOIField()
     height = models.PositiveIntegerField(blank=True, null=True, editable=False)
     width = models.PositiveIntegerField(blank=True, null=True, editable=False)
-    image = VersatileImageField(blank=True, null=True, upload_to='note_images', width_field='width', height_field='height',
-                                ppoi_field='ppoi')
+    image = VersatileImageField(
+        blank=True,
+        null=True,
+        upload_to="note_images",
+        width_field="width",
+        height_field="height",
+        ppoi_field="ppoi",
+    )
     status = models.IntegerField(default=1)
     start = models.DateTimeField(editable=False)
-    show = models.ForeignKey(Show, on_delete=models.CASCADE, related_name='notes', editable=True)
+    show = models.ForeignKey(
+        Show, on_delete=models.CASCADE, related_name="notes", editable=True
+    )
     cba_id = models.IntegerField(blank=True, null=True)
     audio_url = models.TextField(blank=True, editable=False)
-    user = models.ForeignKey(User, editable=False, on_delete=models.CASCADE, related_name='users', default=1)
-    host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name='hosts', null=True)
+    user = models.ForeignKey(
+        User, editable=False, on_delete=models.CASCADE, related_name="users", default=1
+    )
+    host = models.ForeignKey(
+        Host, on_delete=models.CASCADE, related_name="hosts", null=True
+    )
 
     class Meta:
-        ordering = ('timeslot',)
+        ordering = ("timeslot",)
 
     def save(self, *args, **kwargs):
         self.start = self.timeslot.start
diff --git a/program/serializers.py b/program/serializers.py
index 911cc00d2884de36430c2052b0f4299c50d60d5f..9c798b1fc18ce227e5db7aa15a4adf4b4726ab3f 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -25,8 +25,21 @@ from rest_framework import serializers
 
 from profile.models import Profile
 from profile.serializers import ProfileSerializer
-from program.models import Show, Schedule, TimeSlot, Category, FundingCategory, Host, Topic, MusicFocus, Note, Type, Language, \
-    RRule, Link
+from program.models import (
+    Show,
+    Schedule,
+    TimeSlot,
+    Category,
+    FundingCategory,
+    Host,
+    Topic,
+    MusicFocus,
+    Note,
+    Type,
+    Language,
+    RRule,
+    Link,
+)
 from steering.settings import THUMBNAIL_SIZES
 from program.utils import get_audio_url
 
@@ -37,25 +50,39 @@ class UserSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = User
-        fields = ('id', 'username', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'is_superuser', 'password',
-                  'profile')
+        fields = (
+            "id",
+            "username",
+            "first_name",
+            "last_name",
+            "email",
+            "is_staff",
+            "is_active",
+            "is_superuser",
+            "password",
+            "profile",
+        )
 
     def create(self, validated_data):
         """
         Create and return a new User instance, given the validated data.
         """
 
-        profile_data = validated_data.pop('profile') if 'profile' in validated_data else None
+        profile_data = (
+            validated_data.pop("profile") if "profile" in validated_data else None
+        )
 
         user = super(UserSerializer, self).create(validated_data)
         user.date_joined = timezone.now()
-        user.set_password(validated_data['password'])
+        user.set_password(validated_data["password"])
         user.save()
 
         if profile_data:
-            profile = Profile(user=user,
-                              cba_username=profile_data.get('cba_username').strip(),
-                              cba_user_token=profile_data.get('cba_user_token').strip())
+            profile = Profile(
+                user=user,
+                cba_username=profile_data.get("cba_username").strip(),
+                cba_user_token=profile_data.get("cba_user_token").strip(),
+            )
             profile.save()
 
         return user
@@ -65,14 +92,18 @@ class UserSerializer(serializers.ModelSerializer):
         Update and return an existing User instance, given the validated data.
         """
 
-        instance.first_name = validated_data.get('first_name', instance.first_name)
-        instance.last_name = validated_data.get('last_name', instance.last_name)
-        instance.email = validated_data.get('email', instance.email)
-        instance.is_active = validated_data.get('is_active', instance.is_active)
-        instance.is_staff = validated_data.get('is_staff', instance.is_staff)
-        instance.is_superuser = validated_data.get('is_superuser', instance.is_superuser)
+        instance.first_name = validated_data.get("first_name", instance.first_name)
+        instance.last_name = validated_data.get("last_name", instance.last_name)
+        instance.email = validated_data.get("email", instance.email)
+        instance.is_active = validated_data.get("is_active", instance.is_active)
+        instance.is_staff = validated_data.get("is_staff", instance.is_staff)
+        instance.is_superuser = validated_data.get(
+            "is_superuser", instance.is_superuser
+        )
 
-        profile_data = validated_data.pop('profile') if 'profile' in validated_data else None
+        profile_data = (
+            validated_data.pop("profile") if "profile" in validated_data else None
+        )
 
         if profile_data:
             # TODO: How to hook into this from ProfileSerializer without having to call it here?
@@ -81,8 +112,8 @@ class UserSerializer(serializers.ModelSerializer):
             except ObjectDoesNotExist:
                 profile = Profile.objects.create(user=instance, **profile_data)
 
-            profile.cba_username = profile_data.get('cba_username')
-            profile.cba_user_token = profile_data.get('cba_user_token')
+            profile.cba_username = profile_data.get("cba_username")
+            profile.cba_user_token = profile_data.get("cba_user_token")
             profile.save()
 
         instance.save()
@@ -91,18 +122,18 @@ class UserSerializer(serializers.ModelSerializer):
 
 class CategorySerializer(serializers.ModelSerializer):
     # TODO: remove this when the dashboard is updated
-    category = serializers.CharField(source='name')
+    category = serializers.CharField(source="name")
 
     class Meta:
         model = Category
         # TODO: replace `category` with `name` when the dashboard is updated
-        fields = ('category', 'abbrev', 'slug', 'is_active', 'description')
+        fields = ("category", "abbrev", "slug", "is_active", "description")
 
 
 class LinkSerializer(serializers.ModelSerializer):
     class Meta:
         model = Link
-        fields = ('description', 'url')
+        fields = ("description", "url")
 
 
 class HostSerializer(serializers.ModelSerializer):
@@ -122,10 +153,10 @@ class HostSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Host
-        fields = '__all__'
+        fields = "__all__"
 
     def create(self, validated_data):
-        links_data = validated_data.pop('links', [])
+        links_data = validated_data.pop("links", [])
         host = Host.objects.create(**validated_data)
 
         for link_data in links_data:
@@ -138,19 +169,19 @@ class HostSerializer(serializers.ModelSerializer):
         Update and return an existing Host instance, given the validated data.
         """
 
-        instance.name = validated_data.get('name', instance.name)
-        instance.is_active = validated_data.get('is_active', instance.is_active)
-        instance.email = validated_data.get('email', instance.email)
-        instance.website = validated_data.get('website', instance.website)
-        instance.biography = validated_data.get('biography', instance.biography)
-        instance.image = validated_data.get('image', instance.image)
-        instance.ppoi = validated_data.get('ppoi', instance.ppoi)
+        instance.name = validated_data.get("name", instance.name)
+        instance.is_active = validated_data.get("is_active", instance.is_active)
+        instance.email = validated_data.get("email", instance.email)
+        instance.website = validated_data.get("website", instance.website)
+        instance.biography = validated_data.get("biography", instance.biography)
+        instance.image = validated_data.get("image", instance.image)
+        instance.ppoi = validated_data.get("ppoi", instance.ppoi)
 
         if instance.links.count() > 0:
             for link in instance.links.all():
                 link.delete(keep_parents=True)
 
-        if links := validated_data.get('links'):
+        if links := validated_data.get("links"):
             for link_data in links:
                 Link.objects.create(host=instance, **link_data)
 
@@ -162,61 +193,73 @@ class HostSerializer(serializers.ModelSerializer):
 class LanguageSerializer(serializers.ModelSerializer):
     class Meta:
         model = Language
-        fields = ('name', 'is_active')
+        fields = ("name", "is_active")
 
 
 class TopicSerializer(serializers.ModelSerializer):
     # TODO: remove this when the dashboard is updated
-    topic = serializers.CharField(source='name')
+    topic = serializers.CharField(source="name")
 
     class Meta:
         model = Topic
         # TODO: replace `topic` with `name` when the dashboard is updated
-        fields = ('topic', 'abbrev', 'slug', 'is_active')
+        fields = ("topic", "abbrev", "slug", "is_active")
 
 
 class MusicFocusSerializer(serializers.ModelSerializer):
     # TODO: remove this when the dashboard is updated
-    focus = serializers.CharField(source='name')
+    focus = serializers.CharField(source="name")
 
     class Meta:
         model = MusicFocus
         # TODO: replace `focus` with `name` when the dashboard is updated
-        fields = ('focus', 'abbrev', 'slug', 'is_active')
+        fields = ("focus", "abbrev", "slug", "is_active")
 
 
 class TypeSerializer(serializers.ModelSerializer):
     # TODO: remove this when the dashboard is updated
-    type = serializers.CharField(source='name')
+    type = serializers.CharField(source="name")
 
     class Meta:
         model = Type
         # TODO: replace `type` with `name` when the dashboard is updated
-        fields = ('type', 'slug', 'is_active')
+        fields = ("type", "slug", "is_active")
 
 
 class FundingCategorySerializer(serializers.ModelSerializer):
     # TODO: remove this when the dashboard is updated
-    fundingcategory = serializers.CharField(source='name')
+    fundingcategory = serializers.CharField(source="name")
 
     class Meta:
         model = FundingCategory
         # TODO: replace `fundingcategory` with `name` when the dashboard is updated
-        fields = ('fundingcategory', 'abbrev', 'slug', 'is_active')
+        fields = ("fundingcategory", "abbrev", "slug", "is_active")
 
 
 class ShowSerializer(serializers.HyperlinkedModelSerializer):
     owners = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), many=True)
-    category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True)
+    category = serializers.PrimaryKeyRelatedField(
+        queryset=Category.objects.all(), many=True
+    )
     hosts = serializers.PrimaryKeyRelatedField(queryset=Host.objects.all(), many=True)
-    language = serializers.PrimaryKeyRelatedField(queryset=Language.objects.all(), many=True)
+    language = serializers.PrimaryKeyRelatedField(
+        queryset=Language.objects.all(), many=True
+    )
     topic = serializers.PrimaryKeyRelatedField(queryset=Topic.objects.all(), many=True)
-    # TODO: replace `musicfocs` with `music_focus` and remove the source when the dashboard in updated
-    musicfocus = serializers.PrimaryKeyRelatedField(queryset=MusicFocus.objects.all(), source='music_focus', many=True)
+    # TODO: replace `musicfocs` with `music_focus` and remove the source when the dashboard is
+    #  updated
+    musicfocus = serializers.PrimaryKeyRelatedField(
+        queryset=MusicFocus.objects.all(), source="music_focus", many=True
+    )
     type = serializers.PrimaryKeyRelatedField(queryset=Type.objects.all())
-    # TODO: replace `fundingcategory` with `funding_category` and remove the source when the dashboard is updated
-    fundingcategory = serializers.PrimaryKeyRelatedField(queryset=FundingCategory.objects.all(), source='funding_category')
-    predecessor = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(), required=False, allow_null=True)
+    # TODO: replace `fundingcategory` with `funding_category` and remove the source when the
+    #  dashboard is updated
+    fundingcategory = serializers.PrimaryKeyRelatedField(
+        queryset=FundingCategory.objects.all(), source="funding_category"
+    )
+    predecessor = serializers.PrimaryKeyRelatedField(
+        queryset=Show.objects.all(), required=False, allow_null=True
+    )
     thumbnails = serializers.SerializerMethodField()  # Read-only
 
     @staticmethod
@@ -232,22 +275,44 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = Show
-        fields = ('id', 'name', 'slug', 'image', 'ppoi', 'logo', 'short_description', 'description',
-                  'email', 'website', 'type', 'fundingcategory',
-                  'predecessor', 'cba_series_id', 'default_playlist_id', 'category', 'hosts',
-                  'owners', 'language', 'topic', 'musicfocus', 'thumbnails', 'is_active', 'is_public')
+        fields = (
+            "id",
+            "name",
+            "slug",
+            "image",
+            "ppoi",
+            "logo",
+            "short_description",
+            "description",
+            "email",
+            "website",
+            "type",
+            "fundingcategory",
+            "predecessor",
+            "cba_series_id",
+            "default_playlist_id",
+            "category",
+            "hosts",
+            "owners",
+            "language",
+            "topic",
+            "musicfocus",
+            "thumbnails",
+            "is_active",
+            "is_public",
+        )
 
     def create(self, validated_data):
         """
         Create and return a new Show instance, given the validated data.
         """
 
-        owners = validated_data.pop('owners')
-        category = validated_data.pop('category')
-        hosts = validated_data.pop('hosts')
-        language = validated_data.pop('language')
-        topic = validated_data.pop('topic')
-        music_focus = validated_data.pop('music_focus')
+        owners = validated_data.pop("owners")
+        category = validated_data.pop("category")
+        hosts = validated_data.pop("hosts")
+        language = validated_data.pop("language")
+        topic = validated_data.pop("topic")
+        music_focus = validated_data.pop("music_focus")
 
         show = Show.objects.create(**validated_data)
 
@@ -267,29 +332,39 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
         Update and return an existing Show instance, given the validated data.
         """
 
-        instance.name = validated_data.get('name', instance.name)
-        instance.slug = validated_data.get('slug', instance.slug)
-        instance.image = validated_data.get('image', instance.image)
-        instance.ppoi = validated_data.get('ppoi', instance.ppoi)
-        instance.logo = validated_data.get('logo', instance.logo)
-        instance.short_description = validated_data.get('short_description', instance.short_description)
-        instance.description = validated_data.get('description', instance.description)
-        instance.email = validated_data.get('email', instance.email)
-        instance.website = validated_data.get('website', instance.website)
-        instance.cba_series_id = validated_data.get('cba_series_id', instance.cba_series_id)
-        instance.default_playlist_id = validated_data.get('default_playlist_id', instance.default_playlist_id)
-        instance.type = validated_data.get('type', instance.type)
-        instance.funding_category = validated_data.get('funding_category', instance.funding_category)
-        instance.predecessor = validated_data.get('predecessor', instance.predecessor)
-        instance.is_active = validated_data.get('is_active', instance.is_active)
-        instance.is_public = validated_data.get('is_public', instance.is_public)
-
-        instance.owners.set(validated_data.get('owners', instance.owners))
-        instance.category.set(validated_data.get('category', instance.category))
-        instance.hosts.set(validated_data.get('hosts', instance.hosts))
-        instance.language.set(validated_data.get('language', instance.language))
-        instance.topic.set(validated_data.get('topic', instance.topic))
-        instance.music_focus.set(validated_data.get('music_focus', instance.music_focus))
+        instance.name = validated_data.get("name", instance.name)
+        instance.slug = validated_data.get("slug", instance.slug)
+        instance.image = validated_data.get("image", instance.image)
+        instance.ppoi = validated_data.get("ppoi", instance.ppoi)
+        instance.logo = validated_data.get("logo", instance.logo)
+        instance.short_description = validated_data.get(
+            "short_description", instance.short_description
+        )
+        instance.description = validated_data.get("description", instance.description)
+        instance.email = validated_data.get("email", instance.email)
+        instance.website = validated_data.get("website", instance.website)
+        instance.cba_series_id = validated_data.get(
+            "cba_series_id", instance.cba_series_id
+        )
+        instance.default_playlist_id = validated_data.get(
+            "default_playlist_id", instance.default_playlist_id
+        )
+        instance.type = validated_data.get("type", instance.type)
+        instance.funding_category = validated_data.get(
+            "funding_category", instance.funding_category
+        )
+        instance.predecessor = validated_data.get("predecessor", instance.predecessor)
+        instance.is_active = validated_data.get("is_active", instance.is_active)
+        instance.is_public = validated_data.get("is_public", instance.is_public)
+
+        instance.owners.set(validated_data.get("owners", instance.owners))
+        instance.category.set(validated_data.get("category", instance.category))
+        instance.hosts.set(validated_data.get("hosts", instance.hosts))
+        instance.language.set(validated_data.get("language", instance.language))
+        instance.topic.set(validated_data.get("topic", instance.topic))
+        instance.music_focus.set(
+            validated_data.get("music_focus", instance.music_focus)
+        )
 
         instance.save()
         return instance
@@ -299,21 +374,21 @@ class ScheduleSerializer(serializers.ModelSerializer):
     rrule = serializers.PrimaryKeyRelatedField(queryset=RRule.objects.all())
     show = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all())
     # TODO: remove this when the dashboard is updated
-    byweekday = serializers.IntegerField(source='by_weekday')
-    dstart = serializers.DateField(source='first_date')
-    tstart = serializers.TimeField(source='start_time')
-    tend = serializers.TimeField(source='end_time')
-    until = serializers.DateField(source='last_date')
+    byweekday = serializers.IntegerField(source="by_weekday")
+    dstart = serializers.DateField(source="first_date")
+    tstart = serializers.TimeField(source="start_time")
+    tend = serializers.TimeField(source="end_time")
+    until = serializers.DateField(source="last_date")
 
     class Meta:
         model = Schedule
-        fields = '__all__'
+        fields = "__all__"
 
     def create(self, validated_data):
         """Create and return a new Schedule instance, given the validated data."""
 
-        rrule = validated_data.pop('rrule')
-        show = validated_data.pop('show')
+        rrule = validated_data.pop("rrule")
+        show = validated_data.pop("show")
 
         schedule = Schedule.objects.create(**validated_data)
         schedule.rrule = rrule
@@ -325,17 +400,23 @@ class ScheduleSerializer(serializers.ModelSerializer):
     def update(self, instance, validated_data):
         """Update and return an existing Schedule instance, given the validated data."""
 
-        instance.by_weekday = validated_data.get('byweekday', instance.by_weekday)
-        instance.first_date = validated_data.get('dstart', instance.first_date)
-        instance.start_time = validated_data.get('tstart', instance.start_time)
-        instance.end_time = validated_data.get('tend', instance.end_time)
-        instance.last_date = validated_data.get('until', instance.last_date)
-        instance.is_repetition = validated_data.get('is_repetition', instance.is_repetition)
-        instance.default_playlist_id = validated_data.get('default_playlist_id', instance.default_playlist_id)
-        instance.rrule = validated_data.get('rrule', instance.rrule)
-        instance.show = validated_data.get('show', instance.show)
-        instance.add_days_no = validated_data.get('add_days_no', instance.add_days_no)
-        instance.add_business_days_only = validated_data.get('add_business_days_only', instance.add_business_days_only)
+        instance.by_weekday = validated_data.get("byweekday", instance.by_weekday)
+        instance.first_date = validated_data.get("dstart", instance.first_date)
+        instance.start_time = validated_data.get("tstart", instance.start_time)
+        instance.end_time = validated_data.get("tend", instance.end_time)
+        instance.last_date = validated_data.get("until", instance.last_date)
+        instance.is_repetition = validated_data.get(
+            "is_repetition", instance.is_repetition
+        )
+        instance.default_playlist_id = validated_data.get(
+            "default_playlist_id", instance.default_playlist_id
+        )
+        instance.rrule = validated_data.get("rrule", instance.rrule)
+        instance.show = validated_data.get("show", instance.show)
+        instance.add_days_no = validated_data.get("add_days_no", instance.add_days_no)
+        instance.add_business_days_only = validated_data.get(
+            "add_business_days_only", instance.add_business_days_only
+        )
 
         instance.save()
         return instance
@@ -347,7 +428,7 @@ class TimeSlotSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = TimeSlot
-        fields = '__all__'
+        fields = "__all__"
 
     def create(self, validated_data):
         """Create and return a new TimeSlot instance, given the validated data."""
@@ -357,9 +438,11 @@ class TimeSlotSerializer(serializers.ModelSerializer):
         """Update and return an existing Show instance, given the validated data."""
 
         # Only save certain fields
-        instance.memo = validated_data.get('memo', instance.memo)
-        instance.is_repetition = validated_data.get('is_repetition', instance.is_repetition)
-        instance.playlist_id = validated_data.get('playlist_id', instance.playlist_id)
+        instance.memo = validated_data.get("memo", instance.memo)
+        instance.is_repetition = validated_data.get(
+            "is_repetition", instance.is_repetition
+        )
+        instance.playlist_id = validated_data.get("playlist_id", instance.playlist_id)
         instance.save()
         return instance
 
@@ -383,16 +466,16 @@ class NoteSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Note
-        fields = '__all__'
+        fields = "__all__"
 
     def create(self, validated_data):
         """Create and return a new Note instance, given the validated data."""
 
         # Save the creator
-        validated_data['user_id'] = self.context['user_id']
+        validated_data["user_id"] = self.context["user_id"]
 
         # Try to retrieve audio URL from CBA
-        validated_data['audio_url'] = get_audio_url(validated_data['cba_id'])
+        validated_data["audio_url"] = get_audio_url(validated_data["cba_id"])
 
         note = Note.objects.create(**validated_data)
 
@@ -410,17 +493,17 @@ class NoteSerializer(serializers.ModelSerializer):
     def update(self, instance, validated_data):
         """Update and return an existing Note instance, given the validated data."""
 
-        instance.show = validated_data.get('show', instance.show)
-        instance.timeslot = validated_data.get('timeslot', instance.timeslot)
-        instance.title = validated_data.get('title', instance.title)
-        instance.slug = validated_data.get('slug', instance.slug)
-        instance.summary = validated_data.get('summary', instance.summary)
-        instance.content = validated_data.get('content', instance.content)
-        instance.image = validated_data.get('image', instance.image)
-        instance.ppoi = validated_data.get('ppoi', instance.ppoi)
-        instance.status = validated_data.get('status', instance.status)
-        instance.host = validated_data.get('host', instance.host)
-        instance.cba_id = validated_data.get('cba_id', instance.cba_id)
+        instance.show = validated_data.get("show", instance.show)
+        instance.timeslot = validated_data.get("timeslot", instance.timeslot)
+        instance.title = validated_data.get("title", instance.title)
+        instance.slug = validated_data.get("slug", instance.slug)
+        instance.summary = validated_data.get("summary", instance.summary)
+        instance.content = validated_data.get("content", instance.content)
+        instance.image = validated_data.get("image", instance.image)
+        instance.ppoi = validated_data.get("ppoi", instance.ppoi)
+        instance.status = validated_data.get("status", instance.status)
+        instance.host = validated_data.get("host", instance.host)
+        instance.cba_id = validated_data.get("cba_id", instance.cba_id)
         instance.audio_url = get_audio_url(instance.cba_id)
 
         instance.save()
diff --git a/program/utils.py b/program/utils.py
index 4b42ab84e4e8cfee668875b0731eff3e9866837d..729af024a7267e43a02fa07ef72e06caba2dbc20 100644
--- a/program/utils.py
+++ b/program/utils.py
@@ -36,7 +36,11 @@ def parse_datetime(date_string: str) -> datetime:
     except ValueError:
         parsed_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S%z")
 
-    return timezone.make_aware(parsed_datetime) if timezone.is_naive(parsed_datetime) else parsed_datetime
+    return (
+        timezone.make_aware(parsed_datetime)
+        if timezone.is_naive(parsed_datetime)
+        else parsed_datetime
+    )
 
 
 def parse_date(date_string: str) -> date:
@@ -63,20 +67,32 @@ def get_audio_url(cba_id):
     For these contact cba@fro.at
     """
 
-    if cba_id is None or cba_id == '' or CBA_API_KEY == '':
+    if cba_id is None or cba_id == "" or CBA_API_KEY == "":
         return None
     else:
         if DEBUG:
-            url = 'https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id=' + str(cba_id) + '&c=Ml3fASkfwR8'
+            url = (
+                "https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id="
+                + str(cba_id)
+                + "&c=Ml3fASkfwR8"
+            )
         else:
-            url = CBA_AJAX_URL + '?action=cba_ajax_get_filename&post_id=' + str(cba_id) + '&api_key=' + CBA_API_KEY
+            url = (
+                CBA_AJAX_URL
+                + "?action=cba_ajax_get_filename&post_id="
+                + str(cba_id)
+                + "&api_key="
+                + CBA_API_KEY
+            )
 
         audio_url = requests.get(url).json()
 
     return audio_url
 
 
-def get_values(kwargs: Dict[str, str], *keys: str) -> Union[Tuple[Union[int, str, None], ...], int, str, None]:
+def get_values(
+    kwargs: Dict[str, str], *keys: str
+) -> Union[Tuple[Union[int, str, None], ...], int, str, None]:
     """Get the values of the keys from the kwargs."""
 
     def int_if_digit(value: Optional[str]) -> Optional[Union[int, str]]:
@@ -96,8 +112,8 @@ def get_pk_and_slug(kwargs: Dict[str, str]) -> Tuple[Optional[int], Optional[str
     pk, slug = None, None
 
     try:
-        pk = int(kwargs['pk'])
+        pk = int(kwargs["pk"])
     except ValueError:
-        slug = kwargs['pk']
+        slug = kwargs["pk"]
 
     return pk, slug
diff --git a/program/views.py b/program/views.py
index 73073c42be6908cc5b7cdcdc02921bf613a6820d..197f32c226b4abfefb9ffcb15285a97c86550370 100644
--- a/program/views.py
+++ b/program/views.py
@@ -32,10 +32,33 @@ from rest_framework import permissions, status, viewsets
 from rest_framework.pagination import LimitOffsetPagination
 from rest_framework.response import Response
 
-from program.models import Type, MusicFocus, Language, Note, Show, Category, FundingCategory, Topic, TimeSlot, Host, Schedule
-from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSerializer, NoteSerializer, ShowSerializer, \
-    ScheduleSerializer, CategorySerializer, FundingCategorySerializer, TopicSerializer, TimeSlotSerializer, HostSerializer, \
-    UserSerializer
+from program.models import (
+    Type,
+    MusicFocus,
+    Language,
+    Note,
+    Show,
+    Category,
+    FundingCategory,
+    Topic,
+    TimeSlot,
+    Host,
+    Schedule,
+)
+from program.serializers import (
+    TypeSerializer,
+    LanguageSerializer,
+    MusicFocusSerializer,
+    NoteSerializer,
+    ShowSerializer,
+    ScheduleSerializer,
+    CategorySerializer,
+    FundingCategorySerializer,
+    TopicSerializer,
+    TimeSlotSerializer,
+    HostSerializer,
+    UserSerializer,
+)
 from program.utils import parse_date, get_values, get_pk_and_slug
 
 logger = logging.getLogger(__name__)
@@ -45,22 +68,30 @@ def json_day_schedule(request, year=None, month=None, day=None):
     if year is None and month is None and day is None:
         today = timezone.make_aware(datetime.combine(timezone.now(), time(0, 0)))
     else:
-        today = timezone.make_aware(datetime.combine(date(year, month, day), time(0, 0)))
-
-    timeslots = TimeSlot.objects.get_24h_timeslots(today).select_related('schedule').select_related('show')
+        today = timezone.make_aware(
+            datetime.combine(date(year, month, day), time(0, 0))
+        )
+
+    timeslots = (
+        TimeSlot.objects.get_24h_timeslots(today)
+        .select_related("schedule")
+        .select_related("show")
+    )
     schedule = []
     for ts in timeslots:
         entry = {
-            'start': ts.start.strftime('%Y-%m-%d_%H:%M:%S'),
-            'end': ts.end.strftime('%Y-%m-%d_%H:%M:%S'),
-            'title': ts.show.name,
-            'id': ts.show.id,
+            "start": ts.start.strftime("%Y-%m-%d_%H:%M:%S"),
+            "end": ts.end.strftime("%Y-%m-%d_%H:%M:%S"),
+            "title": ts.show.name,
+            "id": ts.show.id,
         }
 
         schedule.append(entry)
 
-    return HttpResponse(json.dumps(schedule, ensure_ascii=False).encode('utf8'),
-                        content_type="application/json; charset=utf-8")
+    return HttpResponse(
+        json.dumps(schedule, ensure_ascii=False).encode("utf8"),
+        content_type="application/json; charset=utf-8",
+    )
 
 
 def json_playout(request):
@@ -75,72 +106,92 @@ def json_playout(request):
          If end not given, it returns all timeslots of the next 7 days
     """
 
-    if request.GET.get('start') is None:
+    if request.GET.get("start") is None:
         start = timezone.make_aware(datetime.combine(timezone.now(), time(0, 0)))
     else:
-        start = timezone.make_aware(datetime.combine(parse_date(request.GET.get('start')), time(0, 0)))
+        start = timezone.make_aware(
+            datetime.combine(parse_date(request.GET.get("start")), time(0, 0))
+        )
 
-    if request.GET.get('end') is None:
+    if request.GET.get("end") is None:
         # If no end was given, return the next week
-        timeslots = TimeSlot.objects.get_7d_timeslots(start).select_related('schedule').select_related('show')
+        timeslots = (
+            TimeSlot.objects.get_7d_timeslots(start)
+            .select_related("schedule")
+            .select_related("show")
+        )
     else:
         # Otherwise return the given timerange
-        end = timezone.make_aware(datetime.combine(parse_date(request.GET.get('end')), time(23, 59)))
-        timeslots = TimeSlot.objects.get_timerange_timeslots(start, end).select_related('schedule').select_related('show')
+        end = timezone.make_aware(
+            datetime.combine(parse_date(request.GET.get("end")), time(23, 59))
+        )
+        timeslots = (
+            TimeSlot.objects.get_timerange_timeslots(start, end)
+            .select_related("schedule")
+            .select_related("show")
+        )
 
     schedule = []
     for ts in timeslots:
-        is_repetition = ' ' + _('REP') if ts.schedule.is_repetition is True else ''
-
-        hosts = ', '.join(ts.show.hosts.values_list('name', flat=True))
-        categories = ', '.join(ts.show.category.values_list('name', flat=True))
-        topics = ', '.join(ts.show.topic.values_list('name', flat=True))
-        music_focus = ', '.join(ts.show.music_focus.values_list('name', flat=True))
-        languages = ', '.join(ts.show.language.values_list('name', flat=True))
-        funding_category = FundingCategory.objects.get(pk=ts.show.funding_category_id) if ts.show.funding_category_id else None
+        is_repetition = " " + _("REP") if ts.schedule.is_repetition is True else ""
+
+        hosts = ", ".join(ts.show.hosts.values_list("name", flat=True))
+        categories = ", ".join(ts.show.category.values_list("name", flat=True))
+        topics = ", ".join(ts.show.topic.values_list("name", flat=True))
+        music_focus = ", ".join(ts.show.music_focus.values_list("name", flat=True))
+        languages = ", ".join(ts.show.language.values_list("name", flat=True))
+        funding_category = (
+            FundingCategory.objects.get(pk=ts.show.funding_category_id)
+            if ts.show.funding_category_id
+            else None
+        )
 
         type_ = Type.objects.get(pk=ts.show.type_id)
 
-        classname = 'default'
+        classname = "default"
 
         if ts.playlist_id is None or ts.playlist_id == 0:
-            classname = 'danger'
+            classname = "danger"
 
         entry = {
-            'id': ts.id,
-            'start': ts.start.strftime('%Y-%m-%dT%H:%M:%S'),
-            'end': ts.end.strftime('%Y-%m-%dT%H:%M:%S'),
-            'title': ts.show.name + is_repetition,  # For JS Calendar
-            'schedule_id': ts.schedule.id,
-            'is_repetition': ts.is_repetition,
-            'playlist_id': ts.playlist_id,
-            'schedule_default_playlist_id': ts.schedule.default_playlist_id,
-            'show_default_playlist_id': ts.show.default_playlist_id,
-            'show_id': ts.show.id,
-            'show_name': ts.show.name + is_repetition,
-            'show_hosts': hosts,
-            'show_type': type_.name,
-            'show_categories': categories,
-            'show_topics': topics,
+            "id": ts.id,
+            "start": ts.start.strftime("%Y-%m-%dT%H:%M:%S"),
+            "end": ts.end.strftime("%Y-%m-%dT%H:%M:%S"),
+            "title": ts.show.name + is_repetition,  # For JS Calendar
+            "schedule_id": ts.schedule.id,
+            "is_repetition": ts.is_repetition,
+            "playlist_id": ts.playlist_id,
+            "schedule_default_playlist_id": ts.schedule.default_playlist_id,
+            "show_default_playlist_id": ts.show.default_playlist_id,
+            "show_id": ts.show.id,
+            "show_name": ts.show.name + is_repetition,
+            "show_hosts": hosts,
+            "show_type": type_.name,
+            "show_categories": categories,
+            "show_topics": topics,
             # TODO: replace `show_musicfocus` with `show_music_focus` when engine is updated
-            'show_musicfocus': music_focus,
-            'show_languages': languages,
-            # TODO: replace `show_fundingcategory` with `show_funding_category` when engine is updated
-            'show_fundingcategory': funding_category.name,
-            'memo': ts.memo,
-            'className': classname,
+            "show_musicfocus": music_focus,
+            "show_languages": languages,
+            # TODO: replace `show_fundingcategory` with `show_funding_category` when engine is
+            #  updated
+            "show_fundingcategory": funding_category.name,
+            "memo": ts.memo,
+            "className": classname,
         }
 
         schedule.append(entry)
 
-    return HttpResponse(json.dumps(schedule, ensure_ascii=False).encode('utf8'),
-                        content_type="application/json; charset=utf-8")
+    return HttpResponse(
+        json.dumps(schedule, ensure_ascii=False).encode("utf8"),
+        content_type="application/json; charset=utf-8",
+    )
 
 
 class APIUserViewSet(viewsets.ModelViewSet):
     """
     /users returns oneself. Superusers see all users. Only superusers may create a user (GET, POST)
-    /users/{pk} retrieves or updates a single user. Non-superusers may only update certain fields (GET, PUT)
+    /users/{pk} retrieves or updates a single user. Non-superusers may only update certain fields
+     (GET, PUT)
 
     Superusers may access and update all users.
     """
@@ -158,7 +209,7 @@ class APIUserViewSet(viewsets.ModelViewSet):
 
     def retrieve(self, request, *args, **kwargs):
         """Returns a single user"""
-        pk = get_values(self.kwargs, 'pk')
+        pk = get_values(self.kwargs, "pk")
 
         # Common users only see themselves
         if not request.user.is_superuser and pk != request.user.id:
@@ -186,15 +237,19 @@ class APIUserViewSet(viewsets.ModelViewSet):
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 
     def update(self, request, *args, **kwargs):
-        pk = get_values(self.kwargs, 'pk')
+        pk = get_values(self.kwargs, "pk")
 
         serializer = UserSerializer(data=request.data)
         # Common users may only edit themselves
         if not request.user.is_superuser and pk != request.user.id:
-            return Response(serializer.initial_data, status=status.HTTP_401_UNAUTHORIZED)
+            return Response(
+                serializer.initial_data, status=status.HTTP_401_UNAUTHORIZED
+            )
 
         user = get_object_or_404(User, pk=pk)
-        serializer = UserSerializer(user, data=request.data, context={'user': request.user})
+        serializer = UserSerializer(
+            user, data=request.data, context={"user": request.user}
+        )
 
         if serializer.is_valid():
             serializer.save()
@@ -235,62 +290,72 @@ class APIShowViewSet(viewsets.ModelViewSet):
         shows = Show.objects.all()
 
         # Filters
-        if self.request.query_params.get('active') == 'true' or self.request.query_params.get('active') == 'false':
+        if (
+            self.request.query_params.get("active") == "true"
+            or self.request.query_params.get("active") == "false"
+        ):
             # Filter currently running shows
             # Get currently running schedules to filter by first
             # For single dates we test if there'll be one in the future (and ignore the until date)
             # TODO: Really consider first_date? (=currently active, not just upcoming ones)
             # Add limit for future?
-            show_ids = Schedule.objects.filter(Q(rrule_id__gt=1,
-                                                 first_date__lte=timezone.now(),
-                                                 last_date__gte=timezone.now()) |
-                                               Q(rrule_id=1,
-                                                 first_date__gte=timezone.now())
-                                               ).distinct().values_list('show_id', flat=True)
+            show_ids = (
+                Schedule.objects.filter(
+                    Q(
+                        rrule_id__gt=1,
+                        first_date__lte=timezone.now(),
+                        last_date__gte=timezone.now(),
+                    )
+                    | Q(rrule_id=1, first_date__gte=timezone.now())
+                )
+                .distinct()
+                .values_list("show_id", flat=True)
+            )
 
             # Filter active shows based on timeslots as well as on the is_active flag
-            # Even if there are future timeslots but is_active=True the show will be considered as inactive
+            # Even if there are future timeslots but is_active=True the show will be considered as
+            # inactive
             shows = Show.objects.filter(id__in=show_ids, is_active=True)
 
-        if self.request.query_params.get('active') == 'false':
+        if self.request.query_params.get("active") == "false":
             # Return all shows except those which are running
             shows = Show.objects.exclude(id__in=show_ids, is_active=True)
 
-        if self.request.query_params.get('public') == 'true':
+        if self.request.query_params.get("public") == "true":
             # Return all public shows
             shows = shows.filter(is_public=True)
 
-        if self.request.query_params.get('public') == 'false':
+        if self.request.query_params.get("public") == "false":
             # Return all public shows
             shows = shows.filter(is_public=False)
 
-        if owner := self.request.query_params.get('owner'):
-            if owner != 'undefined':
+        if owner := self.request.query_params.get("owner"):
+            if owner != "undefined":
                 shows = shows.filter(owners__in=[int(owner)])
 
-        if host := self.request.query_params.get('host'):
-            if host != 'undefined':
+        if host := self.request.query_params.get("host"):
+            if host != "undefined":
                 shows = shows.filter(hosts__in=[int(host)])
 
-        if language := self.request.query_params.get('language'):
-            if language != 'undefined':
+        if language := self.request.query_params.get("language"):
+            if language != "undefined":
                 shows = shows.filter(language__in=[int(language)])
 
-        if type_ := self.request.query_params.get('type'):
-            if type_ != 'undefined':
+        if type_ := self.request.query_params.get("type"):
+            if type_ != "undefined":
                 shows = shows.filter(type__in=[int(type_)])
 
-        if category := self.request.query_params.get('category'):
-            if category != 'undefined':
+        if category := self.request.query_params.get("category"):
+            if category != "undefined":
                 shows = shows.filter(category__in=[int(category)])
 
-        if topic := self.request.query_params.get('topic'):
-            if topic != 'undefined':
+        if topic := self.request.query_params.get("topic"):
+            if topic != "undefined":
                 shows = shows.filter(topic__in=[int(topic)])
 
         # TODO: replace `musicfocus` with `music_focus` when dashboard is updated
-        if music_focus := self.request.query_params.get('musicfocus'):
-            if music_focus != 'undefined':
+        if music_focus := self.request.query_params.get("musicfocus"):
+            if music_focus != "undefined":
                 shows = shows.filter(music_focus__in=[int(music_focus)])
 
         return shows
@@ -317,7 +382,13 @@ class APIShowViewSet(viewsets.ModelViewSet):
 
         pk, slug = get_pk_and_slug(self.kwargs)
 
-        show = get_object_or_404(Show, pk=pk) if pk else get_object_or_404(Show, slug=slug) if slug else None
+        show = (
+            get_object_or_404(Show, pk=pk)
+            if pk
+            else get_object_or_404(Show, slug=slug)
+            if slug
+            else None
+        )
 
         serializer = ShowSerializer(show)
 
@@ -329,18 +400,22 @@ class APIShowViewSet(viewsets.ModelViewSet):
         Common users may only update shows they own
         """
 
-        pk = get_values(self.kwargs, 'pk')
+        pk = get_values(self.kwargs, "pk")
 
-        if not request.user.is_superuser and pk not in request.user.shows.values_list('id', flat=True):
+        if not request.user.is_superuser and pk not in request.user.shows.values_list(
+            "id", flat=True
+        ):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         show = get_object_or_404(Show, pk=pk)
-        serializer = ShowSerializer(show, data=request.data, context={'user': request.user})
+        serializer = ShowSerializer(
+            show, data=request.data, context={"user": request.user}
+        )
 
         if serializer.is_valid():
             # Common users mustn't edit the show's name
             if not request.user.is_superuser:
-                serializer.validated_data['name'] = show.name
+                serializer.validated_data["name"] = show.name
             serializer.save()
             return Response(serializer.data)
 
@@ -355,7 +430,7 @@ class APIShowViewSet(viewsets.ModelViewSet):
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        pk = get_values(self.kwargs, 'pk')
+        pk = get_values(self.kwargs, "pk")
 
         Show.objects.get(pk=pk).delete()
 
@@ -377,7 +452,7 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
 
     def get_queryset(self):
-        show_pk = get_values(self.kwargs, 'show_pk')
+        show_pk = get_values(self.kwargs, "show_pk")
 
         if show_pk:
             return Schedule.objects.filter(show=show_pk)
@@ -385,9 +460,13 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
         return Schedule.objects.all()
 
     def retrieve(self, request, *args, **kwargs):
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
-        schedule = get_object_or_404(Schedule, pk=pk, show=show_pk) if show_pk else get_object_or_404(Schedule, pk=pk)
+        schedule = (
+            get_object_or_404(Schedule, pk=pk, show=show_pk)
+            if show_pk
+            else get_object_or_404(Schedule, pk=pk)
+        )
 
         serializer = ScheduleSerializer(schedule)
 
@@ -404,21 +483,25 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
-        # Only allow creating when calling /shows/{show_pk}/schedules/ and with ehe `schedule` JSON object
-        if show_pk is None or 'schedule' not in request.data:
+        # Only allow creating when calling /shows/{show_pk}/schedules/ and with ehe `schedule` JSON
+        # object
+        if show_pk is None or "schedule" not in request.data:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         # First create submit -> return projected timeslots and collisions
-        if 'solutions' not in request.data:
-            return Response(Schedule.make_conflicts(request.data['schedule'], pk, show_pk), status=status.HTTP_409_CONFLICT)
+        if "solutions" not in request.data:
+            return Response(
+                Schedule.make_conflicts(request.data["schedule"], pk, show_pk),
+                status=status.HTTP_409_CONFLICT,
+            )
 
         # Otherwise try to resolve
         resolution = Schedule.resolve_conflicts(request.data, pk, show_pk)
 
         # If resolution went well
-        if 'projected' not in resolution:
+        if "projected" not in resolution:
             return Response(resolution, status=status.HTTP_201_CREATED)
 
         # Otherwise return conflicts
@@ -434,14 +517,17 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
-        # Only allow updating when calling /shows/{show_pk}/schedules/{pk}/ and with the `schedule` JSON object
-        if show_pk is None or 'schedule' not in request.data:
+        # Only allow updating when calling /shows/{show_pk}/schedules/{pk}/ and with the `schedule`
+        # JSON object
+        if show_pk is None or "schedule" not in request.data:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
         # If default playlist id or repetition are given, just update
-        if default_playlist_id := request.data.get('schedule').get('default_playlist_id'):
+        if default_playlist_id := request.data.get("schedule").get(
+            "default_playlist_id"
+        ):
             schedule = get_object_or_404(Schedule, pk=pk, show=show_pk)
             schedule.default_playlist_id = int(default_playlist_id)
             schedule.save()
@@ -449,7 +535,7 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
             serializer = ScheduleSerializer(schedule)
             return Response(serializer.data)
 
-        if is_repetition := request.data.get('schedule').get('is_repetition'):
+        if is_repetition := request.data.get("schedule").get("is_repetition"):
             schedule = get_object_or_404(Schedule, pk=pk, show=show_pk)
             schedule.is_repetition = bool(is_repetition)
             schedule.save()
@@ -458,14 +544,17 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
             return Response(serializer.data)
 
         # First update submit -> return projected timeslots and collisions
-        if 'solutions' not in request.data:
-            return Response(Schedule.make_conflicts(request.data['schedule'], pk, show_pk), status=status.HTTP_409_CONFLICT)
+        if "solutions" not in request.data:
+            return Response(
+                Schedule.make_conflicts(request.data["schedule"], pk, show_pk),
+                status=status.HTTP_409_CONFLICT,
+            )
 
         # Otherwise try to resolve
         resolution = Schedule.resolve_conflicts(request.data, pk, show_pk)
 
         # If resolution went well
-        if 'projected' not in resolution:
+        if "projected" not in resolution:
             return Response(resolution)
 
         # Otherwise return conflicts
@@ -480,7 +569,7 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
         # Only allow deleting when calling /shows/{show_pk}/schedules/{pk}
         if show_pk is None:
@@ -493,16 +582,22 @@ class APIScheduleViewSet(viewsets.ModelViewSet):
 
 class APITimeSlotViewSet(viewsets.ModelViewSet):
     """
-    /timeslots returns timeslots of the next 60 days (GET). Timeslots may only be added by creating/updating a schedule
+    /timeslots returns timeslots of the next 60 days (GET). Timeslots may only be added by
+     creating/updating a schedule
     /timeslots/{pk} eturns the given timeslot (GET)
     /timeslots/?start={start_date}&end={end_date} returns timeslots within the time range (GET)
     /shows/{show_pk}/timeslots returns timeslots of the show (GET, POST)
-    /shows/{show_pk}/timeslots?surrounding returns the 10 nearest timeslots for the current date (GET)
+    /shows/{show_pk}/timeslots?surrounding returns the 10 nearest timeslots for the current date
+     (GET)
     /shows/{show_pk}/timeslots/{pk} returns a timeslots by its ID (GET, PUT, DELETE)
-    /shows/{show_pk}/timeslots/?start={start_date}&end={end_date} returns timeslots of the show within the time range
-    /shows/{show_pk}/schedules/{schedule_pk}/timeslots returns all timeslots of the schedule (GET, POST)
-    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{pk} returns a timeslot by its ID (GET, DELETE). If PUT, the next repetition is returned or nothing if the next timeslot isn't one
-    /shows/{show_pk}/schedules/{schedule_pk}/timeslots?start={start_date}&end={end_date} returns all timeslots of the schedule within the time range
+    /shows/{show_pk}/timeslots/?start={start_date}&end={end_date} returns timeslots of the show
+     within the time range
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots returns all timeslots of the schedule (GET,
+     POST)
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{pk} returns a timeslot by its ID (GET,
+     DELETE). If PUT, the next repetition is returned or nothing if the next timeslot isn't one
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots?start={start_date}&end={end_date} returns
+     all timeslots of the schedule within the time range
     """
 
     permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
@@ -511,32 +606,52 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
     queryset = TimeSlot.objects.none()
 
     def get_queryset(self):
-        show_pk, schedule_pk = get_values(self.kwargs, 'show_pk', 'schedule_pk')
+        show_pk, schedule_pk = get_values(self.kwargs, "show_pk", "schedule_pk")
         # Filters
 
         # Return next 60 days by default
         start = timezone.make_aware(datetime.combine(timezone.now(), time(0, 0)))
         end = start + timedelta(days=60)
 
-        if ('start' in self.request.query_params) and ('end' in self.request.query_params):
-            start = timezone.make_aware(datetime.combine(parse_date(self.request.query_params.get('start')), time(0, 0)))
-            end = timezone.make_aware(datetime.combine(parse_date(self.request.query_params.get('end')), time(23, 59)))
-
-        default_order = '-start'
-        order = self.request.query_params.get('order', default_order)
+        if ("start" in self.request.query_params) and (
+            "end" in self.request.query_params
+        ):
+            start = timezone.make_aware(
+                datetime.combine(
+                    parse_date(self.request.query_params.get("start")), time(0, 0)
+                )
+            )
+            end = timezone.make_aware(
+                datetime.combine(
+                    parse_date(self.request.query_params.get("end")), time(23, 59)
+                )
+            )
+
+        default_order = "-start"
+        order = self.request.query_params.get("order", default_order)
 
         # If someone tries to sort by a field that isn't available on the model
         # we silently ignore that and use the default sort order.
         model_fields = [field.name for field in TimeSlot._meta.get_fields()]
-        if order.lstrip('-') not in model_fields:
+        if order.lstrip("-") not in model_fields:
             order = default_order
 
-        if 'surrounding' in self.request.query_params:
+        if "surrounding" in self.request.query_params:
             now = timezone.now()
 
-            nearest_timeslots_in_future = TimeSlot.objects.filter(start__gte=now).order_by('start').values_list('id', flat=True)[:5]
-            nearest_timeslots_in_past = TimeSlot.objects.filter(start__lt=now).order_by('-start').values_list('id', flat=True)[:5]
-            relevant_timeslot_ids = list(nearest_timeslots_in_future) + list(nearest_timeslots_in_past)
+            nearest_timeslots_in_future = (
+                TimeSlot.objects.filter(start__gte=now)
+                .order_by("start")
+                .values_list("id", flat=True)[:5]
+            )
+            nearest_timeslots_in_past = (
+                TimeSlot.objects.filter(start__lt=now)
+                .order_by("-start")
+                .values_list("id", flat=True)[:5]
+            )
+            relevant_timeslot_ids = list(nearest_timeslots_in_future) + list(
+                nearest_timeslots_in_past
+            )
 
             return TimeSlot.objects.filter(id__in=relevant_timeslot_ids).order_by(order)
 
@@ -548,7 +663,9 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         #     Returns timeslots of the given show and schedule
         #
         if show_pk and schedule_pk:
-            return TimeSlot.objects.filter(show=show_pk, schedule=schedule_pk, start__gte=start, end__lte=end).order_by(order)
+            return TimeSlot.objects.filter(
+                show=show_pk, schedule=schedule_pk, start__gte=start, end__lte=end
+            ).order_by(order)
 
         #
         #     /shows/1/timeslots/
@@ -556,7 +673,9 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         #     Returns timeslots of the show
         #
         elif show_pk and schedule_pk is None:
-            return TimeSlot.objects.filter(show=show_pk, start__gte=start, end__lte=end).order_by(order)
+            return TimeSlot.objects.filter(
+                show=show_pk, start__gte=start, end__lte=end
+            ).order_by(order)
 
         #
         #     /timeslots/
@@ -564,10 +683,12 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         #     Returns all timeslots
         #
         else:
-            return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by(order)
+            return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by(
+                order
+            )
 
     def retrieve(self, request, *args, **kwargs):
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
         if show_pk:
             timeslot = get_object_or_404(TimeSlot, pk=pk, show=show_pk)
@@ -587,16 +708,24 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
     def update(self, request, *args, **kwargs):
         """Link a playlist_id to a timeslot"""
 
-        pk, show_pk, schedule_pk = get_values(self.kwargs, 'pk', 'show_pk', 'schedule_pk')
+        pk, show_pk, schedule_pk = get_values(
+            self.kwargs, "pk", "show_pk", "schedule_pk"
+        )
 
-        if not request.user.is_superuser and show_pk not in request.user.shows.values_lis('id', flat=True):
+        if (
+            not request.user.is_superuser
+            and show_pk not in request.user.shows.values_lis("id", flat=True)
+        ):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        # Update is only allowed when calling /shows/1/schedules/1/timeslots/1 and if user owns the show
+        # Update is only allowed when calling /shows/1/schedules/1/timeslots/1 and if user owns the
+        # show
         if schedule_pk is None or show_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
-        timeslot = get_object_or_404(TimeSlot, pk=pk, schedule=schedule_pk, show=show_pk)
+        timeslot = get_object_or_404(
+            TimeSlot, pk=pk, schedule=schedule_pk, show=show_pk
+        )
 
         serializer = TimeSlotSerializer(timeslot, data=request.data)
         if serializer.is_valid():
@@ -624,7 +753,7 @@ class APITimeSlotViewSet(viewsets.ModelViewSet):
         if not request.user.is_superuser:
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        pk, show_pk = get_values(self.kwargs, 'pk', 'show_pk')
+        pk, show_pk = get_values(self.kwargs, "pk", "show_pk")
 
         # Only allow when calling endpoint starting with /shows/1/...
         if show_pk is None:
@@ -647,8 +776,10 @@ class APINoteViewSet(viewsets.ModelViewSet):
     /shows/{show_pk}/notes/{pk} returns a note by its ID (GET)
     /shows/{show_pk}/timeslots/{timeslot_pk}/note/ returns a note of the timeslot (GET)
     /shows/{show_pk}/timeslots/{timeslot_pk}/note/{pk} returns a note by its ID (GET)
-    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note returns a note to the timeslot (GET, POST).
-    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note/{pk} returns a note by its ID (GET, PUT, DELETE)
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note returns a note to the
+     timeslot (GET, POST).
+    /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note/{pk} returns a note by
+     its ID (GET, PUT, DELETE)
 
     Superusers may access and update all notes
     """
@@ -659,7 +790,7 @@ class APINoteViewSet(viewsets.ModelViewSet):
     pagination_class = LimitOffsetPagination
 
     def get_queryset(self):
-        timeslot_pk, show_pk = get_values(self.kwargs, 'timeslot_pk', 'show_pk')
+        timeslot_pk, show_pk = get_values(self.kwargs, "timeslot_pk", "show_pk")
 
         # Endpoints
 
@@ -690,21 +821,21 @@ class APINoteViewSet(viewsets.ModelViewSet):
 
         # Filters
 
-        if ids := self.request.query_params.get('ids'):
+        if ids := self.request.query_params.get("ids"):
             # Filter notes by their IDs
-            note_ids = list(map(int, ids.split(',')))
+            note_ids = list(map(int, ids.split(",")))
             notes = notes.filter(id__in=note_ids)
 
-        if host := self.request.query_params.get('host'):
+        if host := self.request.query_params.get("host"):
             # Filter notes by host
             notes = notes.filter(host=int(host))
 
-        if owner := self.request.query_params.get('owner'):
+        if owner := self.request.query_params.get("owner"):
             # Filter notes by show owner: all notes the user may edit
             shows = Show.objects.filter(owners=int(owner))
             notes = notes.filter(show__in=shows)
 
-        if user := self.request.query_params.get('user'):
+        if user := self.request.query_params.get("user"):
             # Filter notes by their creator
             notes = notes.filter(user=int(user))
 
@@ -713,21 +844,30 @@ class APINoteViewSet(viewsets.ModelViewSet):
     def create(self, request, *args, **kwargs):
         """Create a note"""
 
-        show_pk, schedule_pk, timeslot_pk = get_values(self.kwargs, 'show_pk', 'schedule_pk', 'timelost_pk')
+        show_pk, schedule_pk, timeslot_pk = get_values(
+            self.kwargs, "show_pk", "schedule_pk", "timelost_pk"
+        )
 
-        if not request.user.is_superuser and show_pk not in request.user.shows.values_list('id', flat=True):
+        if (
+            not request.user.is_superuser
+            and show_pk not in request.user.shows.values_list("id", flat=True)
+        ):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         # Only create a note if show_id, timeslot_id and schedule_id is given
         if show_pk is None or schedule_pk is None or timeslot_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
-        serializer = NoteSerializer(data=request.data, context={'user_id': request.user.id})
+        serializer = NoteSerializer(
+            data=request.data, context={"user_id": request.user.id}
+        )
 
         if serializer.is_valid():
-            hosts = Host.objects.filter(shows__in=request.user.shows.values_list('id', flat=True))
-            if not request.user.is_superuser and request.data['host'] not in hosts:
-                serializer.validated_data['host'] = None
+            hosts = Host.objects.filter(
+                shows__in=request.user.shows.values_list("id", flat=True)
+            )
+            if not request.user.is_superuser and request.data["host"] not in hosts:
+                serializer.validated_data["host"] = None
 
             serializer.save()
             return Response(serializer.data, status=status.HTTP_201_CREATED)
@@ -744,7 +884,9 @@ class APINoteViewSet(viewsets.ModelViewSet):
         /shows/1/timeslots/1/note/1
         /shows/1/schedules/1/timeslots/1/note/1
         """
-        pk, show_pk, schedule_pk, timeslot_pk = get_values(self.kwargs, 'pk', 'show_pk', 'schedule_pk', 'timeslot_pk')
+        pk, show_pk, schedule_pk, timeslot_pk = get_values(
+            self.kwargs, "pk", "show_pk", "schedule_pk", "timeslot_pk"
+        )
 
         #
         #      /shows/1/notes/1
@@ -775,12 +917,18 @@ class APINoteViewSet(viewsets.ModelViewSet):
         return Response(serializer.data)
 
     def update(self, request, *args, **kwargs):
-        pk, show_pk, schedule_pk, timeslot_pk = get_values(self.kwargs, 'pk', 'show_pk', 'schedule_pk', 'timeslot_pk')
-
-        if not request.user.is_superuser and show_pk not in request.user.shows.values_list('id', flat=True):
+        pk, show_pk, schedule_pk, timeslot_pk = get_values(
+            self.kwargs, "pk", "show_pk", "schedule_pk", "timeslot_pk"
+        )
+
+        if (
+            not request.user.is_superuser
+            and show_pk not in request.user.shows.values_list("id", flat=True)
+        ):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
-        # Allow PUT only when calling /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note/{pk}
+        # Allow PUT only when calling
+        #  /shows/{show_pk}/schedules/{schedule_pk}/timeslots/{timeslot_pk}/note/{pk}
         if show_pk is None or schedule_pk is None or timeslot_pk is None:
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
@@ -789,10 +937,14 @@ class APINoteViewSet(viewsets.ModelViewSet):
         serializer = NoteSerializer(note, data=request.data)
 
         if serializer.is_valid():
-            hosts = Host.objects.filter(shows__in=request.user.shows.values_list('id', flat=True))
+            hosts = Host.objects.filter(
+                shows__in=request.user.shows.values_list("id", flat=True)
+            )
             # Don't assign a host the user mustn't edit. Reassign the original value instead
-            if not request.user.is_superuser and int(request.data['host']) not in hosts:
-                serializer.validated_data['host'] = Host.objects.filter(pk=note.host_id)[0]
+            if not request.user.is_superuser and int(request.data["host"]) not in hosts:
+                serializer.validated_data["host"] = Host.objects.filter(
+                    pk=note.host_id
+                )[0]
 
             serializer.save()
             return Response(serializer.data)
@@ -800,9 +952,14 @@ class APINoteViewSet(viewsets.ModelViewSet):
         return Response(status=status.HTTP_400_BAD_REQUEST)
 
     def destroy(self, request, *args, **kwargs):
-        pk, show_pk, schedule_pk, timeslot_pk = get_values(self.kwargs, 'pk', 'show_pk', 'schedule_pk', 'timeslot_pk')
-
-        if not request.user.is_superuser and show_pk not in request.user.shows.values_list('id', flat=True):
+        pk, show_pk, schedule_pk, timeslot_pk = get_values(
+            self.kwargs, "pk", "show_pk", "schedule_pk", "timeslot_pk"
+        )
+
+        if (
+            not request.user.is_superuser
+            and show_pk not in request.user.shows.values_list("id", flat=True)
+        ):
             return Response(status=status.HTTP_401_UNAUTHORIZED)
 
         if pk is None or show_pk is None or schedule_pk is None or timeslot_pk is None:
@@ -819,10 +976,10 @@ class ActiveInactiveViewSet(viewsets.ModelViewSet):
     def get_queryset(self: viewsets.ModelViewSet):
         """Filters"""
 
-        if self.request.query_params.get('active') == 'true':
+        if self.request.query_params.get("active") == "true":
             return self.queryset.model.objects.filter(is_active=True)
 
-        if self.request.query_params.get('active') == 'false':
+        if self.request.query_params.get("active") == "false":
             return self.queryset.model.objects.filter(is_active=False)
 
         return self.queryset.model.objects.all()
diff --git a/steering/oidc_provider_settings.py b/steering/oidc_provider_settings.py
index c2641cb8cfb94fb50de06824e4dbd2a261f20dbe..e0f5537e313c8f8f1356c1c6c3d5a7399a4c7019 100644
--- a/steering/oidc_provider_settings.py
+++ b/steering/oidc_provider_settings.py
@@ -24,33 +24,32 @@ from oidc_provider.lib.claims import ScopeClaims
 
 class AuraScopeClaims(ScopeClaims):
     info_username = (
-        _(u'username'),
-        _(u'Your username.'),
+        _("username"),
+        _("Your username."),
     )
 
     def scope_username(self):
         dic = {
-            'username': self.user.username,
+            "username": self.user.username,
             # 'privileged': (self.user.is_staff or self.user.is_superuser)
-            'privileged': self.user.is_superuser
+            "privileged": self.user.is_superuser,
         }
 
         return dic
 
     info_aura_shows = (
-        _(u'AURA Shows'),
-        _(u'AURA shows you have access to.'),
+        _("AURA Shows"),
+        _("AURA shows you have access to."),
     )
 
     def scope_aura_shows(self):
         from program.models import Show
 
         # TODO: should add filter `is_active=True` ?
-        public_show_slugs = list(Show.objects.filter(is_public=True).values_list('slug', flat=True))
-        show_slugs = list(self.user.shows.all().values_list('slug', flat=True))
-        dic = {
-            'shows': show_slugs,
-            'public-shows': public_show_slugs
-        }
+        public_show_slugs = list(
+            Show.objects.filter(is_public=True).values_list("slug", flat=True)
+        )
+        show_slugs = list(self.user.shows.all().values_list("slug", flat=True))
+        dic = {"shows": show_slugs, "public-shows": public_show_slugs}
 
         return dic
diff --git a/steering/settings.py b/steering/settings.py
index 773bec676129b8edcf0dcffb5d62a3ab4f2432d3..0bf1ecb629b30eb235ae28949f780cb37e2e6a81 100644
--- a/steering/settings.py
+++ b/steering/settings.py
@@ -9,134 +9,129 @@ from corsheaders.defaults import default_headers
 
 PROJECT_DIR = os.path.dirname(__file__)
 
-LOCALE_PATHS = (
-    os.path.join(PROJECT_DIR, 'locale'),
-)
+LOCALE_PATHS = (os.path.join(PROJECT_DIR, "locale"),)
 
-MEDIA_ROOT = os.path.join(PROJECT_DIR, 'site_media')
-MEDIA_URL = '/site_media/'
+MEDIA_ROOT = os.path.join(PROJECT_DIR, "site_media")
+MEDIA_URL = "/site_media/"
 
-STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
-STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(PROJECT_DIR, "static")
+STATIC_URL = "/static/"
 
-ROOT_URLCONF = 'steering.urls'
+ROOT_URLCONF = "steering.urls"
 
 env = environ.Env()
-env.read_env(env_file=PROJECT_DIR + '/../.env')
+env.read_env(env_file=PROJECT_DIR + "/../.env")
 
-DEBUG = env.bool('DEBUG', default=False)
+DEBUG = env.bool("DEBUG", default=False)
 SITE_ID = 1
 ADMINS = ()
 MANAGERS = ADMINS
 
 # Must be set if DEBUG is False
-ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['127.0.0.1', 'localhost'])
+ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["127.0.0.1", "localhost"])
 
 # Whitelist IPs that access the API
-CORS_ORIGIN_WHITELIST = env.list('CORS_ORIGIN_WHITELIST', default=(
-    'http://localhost:8080',
-    'http://localhost:8040'
-))
+CORS_ORIGIN_WHITELIST = env.list(
+    "CORS_ORIGIN_WHITELIST", default=("http://localhost:8080", "http://localhost:8040")
+)
 CORS_ALLOW_CREDENTIALS = True
 CORS_ALLOW_HEADERS = list(default_headers) + [
-    'content-disposition',
+    "content-disposition",
 ]
 
 # if we are in a virtual environment, we use SQLite and enable debug
-if os.environ.get('VIRTUAL_ENV'):
+if os.environ.get("VIRTUAL_ENV"):
     DEBUG = True
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.sqlite3',
-            'NAME': os.path.join(PROJECT_DIR, "db.sqlite3")
+        "default": {
+            "ENGINE": "django.db.backends.sqlite3",
+            "NAME": os.path.join(PROJECT_DIR, "db.sqlite3"),
         }
     }
 else:
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.postgresql',
-            'NAME': env.str('POSTGRES_DB', default='steering'),
-            'USER': env.str('POSTGRES_USER', default='steering'),
-            'PASSWORD': env.str('POSTGRES_PASSWORD'),
-            'HOST': env.str('POSTGRES_HOST', default='steering-postgres'),
-            'PORT': env.str('POSTGRES_PORT', default='5432'),
+        "default": {
+            "ENGINE": "django.db.backends.postgresql",
+            "NAME": env.str("POSTGRES_DB", default="steering"),
+            "USER": env.str("POSTGRES_USER", default="steering"),
+            "PASSWORD": env.str("POSTGRES_PASSWORD"),
+            "HOST": env.str("POSTGRES_HOST", default="steering-postgres"),
+            "PORT": env.str("POSTGRES_PORT", default="5432"),
         },
     }
 
-CACHE_BACKEND = 'locmem://'
+CACHE_BACKEND = "locmem://"
 
 # LOCALIZATION
-TIME_ZONE = env.str('TIME_ZONE', default='Europe/Vienna')
-LANGUAGE_CODE = env.str('LANGUAGE_CODE', default='de')
+TIME_ZONE = env.str("TIME_ZONE", default="Europe/Vienna")
+LANGUAGE_CODE = env.str("LANGUAGE_CODE", default="de")
 USE_I18N = True
 USE_L10N = True
 
-SECRET_KEY = env.str('SECRET_KEY')
+SECRET_KEY = env.str("SECRET_KEY")
 
 TEMPLATES = [
     {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [
-            os.path.join(PROJECT_DIR, 'templates')
-        ],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.contrib.auth.context_processors.auth',
-                'django.template.context_processors.request',
-                'django.template.context_processors.debug',
-                'django.template.context_processors.i18n',
-                'django.template.context_processors.media',
-                'django.template.context_processors.static',
-                'django.template.context_processors.tz',
-                'django.contrib.messages.context_processors.messages',
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [os.path.join(PROJECT_DIR, "templates")],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            "context_processors": [
+                "django.contrib.auth.context_processors.auth",
+                "django.template.context_processors.request",
+                "django.template.context_processors.debug",
+                "django.template.context_processors.i18n",
+                "django.template.context_processors.media",
+                "django.template.context_processors.static",
+                "django.template.context_processors.tz",
+                "django.contrib.messages.context_processors.messages",
             ],
         },
     },
 ]
 
 MIDDLEWARE = (
-    'corsheaders.middleware.CorsMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
+    "corsheaders.middleware.CorsMiddleware",
+    "django.middleware.common.CommonMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "django.middleware.csrf.CsrfViewMiddleware",
+    "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "django.contrib.messages.middleware.MessageMiddleware",
 )
 
 REST_FRAMEWORK = {
     # Use Django's standard `django.contrib.auth` permissions,
     # or allow read-only access for unauthenticated users.
-    'DEFAULT_PERMISSION_CLASSES': [
-        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
+    "DEFAULT_PERMISSION_CLASSES": [
+        "rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly"
     ],
-    'DEFAULT_AUTHENTICATION_CLASSES': [
-        'program.auth.OidcOauth2Auth',
+    "DEFAULT_AUTHENTICATION_CLASSES": [
+        "program.auth.OidcOauth2Auth",
     ],
 }
 
 INSTALLED_APPS = (
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.sites',
-    'django.contrib.messages',
-    'django.contrib.admin',
-    'django.contrib.staticfiles',
-    'program',
-    'profile',
-    'versatileimagefield',
-    'rest_framework',
-    'rest_framework_nested',
-    'oidc_provider',
-    'corsheaders',
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.sites",
+    "django.contrib.messages",
+    "django.contrib.admin",
+    "django.contrib.staticfiles",
+    "program",
+    "profile",
+    "versatileimagefield",
+    "rest_framework",
+    "rest_framework_nested",
+    "oidc_provider",
+    "corsheaders",
 )
 
-DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
 
 # Set the desired sizes for your thumbnails (px)
 # Will apply to all uploaded images
-THUMBNAIL_SIZES = ['640x480', '200x200', '150x150']
+THUMBNAIL_SIZES = ["640x480", "200x200", "150x150"]
 
 # When generating schedules/timeslots:
 # If until date wasn't set manually, add x days to the start date
@@ -147,21 +142,21 @@ AUTO_SET_UNTIL_DATE_TO_DAYS_IN_FUTURE = 365
 AUTO_SET_UNTIL_DATE_TO_END_OF_YEAR = True
 
 # URL to CBA - Cultural Broadcasting Archive
-CBA_URL = 'https://cba.fro.at'
+CBA_URL = "https://cba.fro.at"
 
 # Contact cba@fro.at to get whitelisted and get an API KEY
 # Leave empty to disable requests to CBA
-CBA_API_KEY = ''
+CBA_API_KEY = ""
 
 # URL to CBA ajax handler (used for retrieving additional data or increasing stream counter)
-CBA_AJAX_URL = CBA_URL + '/wp-admin/admin-ajax.php'
+CBA_AJAX_URL = CBA_URL + "/wp-admin/admin-ajax.php"
 
 # URL to CBA's REST API with trailing slash
-CBA_REST_API_URL = CBA_URL + '/wp-json/wp/v2/'
+CBA_REST_API_URL = CBA_URL + "/wp-json/wp/v2/"
 
 # OIDC Provider Settings
 USE_TZ = True  # django-oidc-provider needs timezones in database
-LOGIN_URL = '/admin/login/'  # Login page OIDC redirects to
-OIDC_EXTRA_SCOPE_CLAIMS = 'steering.oidc_provider_settings.AuraScopeClaims'
+LOGIN_URL = "/admin/login/"  # Login page OIDC redirects to
+OIDC_EXTRA_SCOPE_CLAIMS = "steering.oidc_provider_settings.AuraScopeClaims"
 
 # WSGI_APPLICATION = 'steering.wsgi.application';
diff --git a/steering/urls.py b/steering/urls.py
index fbe50aece5771607b06f82a1139671c02bc5d7c4..e2be51e364a859eef027b8cc911293d79da33c67 100644
--- a/steering/urls.py
+++ b/steering/urls.py
@@ -22,62 +22,83 @@ from django.urls import include, path
 from django.contrib import admin
 from rest_framework_nested import routers
 
-from program.views import APIUserViewSet, APIHostViewSet, APIShowViewSet, APIScheduleViewSet, APITimeSlotViewSet, \
-    APINoteViewSet, APICategoryViewSet, APITypeViewSet, APITopicViewSet, APIMusicFocusViewSet, APIFundingCategoryViewSet, \
-    APILanguageViewSet, json_day_schedule, json_playout
+from program.views import (
+    APIUserViewSet,
+    APIHostViewSet,
+    APIShowViewSet,
+    APIScheduleViewSet,
+    APITimeSlotViewSet,
+    APINoteViewSet,
+    APICategoryViewSet,
+    APITypeViewSet,
+    APITopicViewSet,
+    APIMusicFocusViewSet,
+    APIFundingCategoryViewSet,
+    APILanguageViewSet,
+    json_day_schedule,
+    json_playout,
+)
 
 admin.autodiscover()
 
 router = routers.DefaultRouter()
-router.register(r'users', APIUserViewSet)
-router.register(r'hosts', APIHostViewSet)
-router.register(r'shows', APIShowViewSet)
-router.register(r'schedules', APIScheduleViewSet)
-router.register(r'timeslots', APITimeSlotViewSet)
-router.register(r'notes', APINoteViewSet)
-router.register(r'categories', APICategoryViewSet)
-router.register(r'topics', APITopicViewSet)
-router.register(r'types', APITypeViewSet)
-router.register(r'musicfocus', APIMusicFocusViewSet)
-router.register(r'fundingcategories', APIFundingCategoryViewSet)
-router.register(r'languages', APILanguageViewSet)
+router.register(r"users", APIUserViewSet)
+router.register(r"hosts", APIHostViewSet)
+router.register(r"shows", APIShowViewSet)
+router.register(r"schedules", APIScheduleViewSet)
+router.register(r"timeslots", APITimeSlotViewSet)
+router.register(r"notes", APINoteViewSet)
+router.register(r"categories", APICategoryViewSet)
+router.register(r"topics", APITopicViewSet)
+router.register(r"types", APITypeViewSet)
+router.register(r"musicfocus", APIMusicFocusViewSet)
+router.register(r"fundingcategories", APIFundingCategoryViewSet)
+router.register(r"languages", APILanguageViewSet)
 
 # Nested Routers
 
-show_router = routers.NestedSimpleRouter(router, r'shows', lookup='show')
+show_router = routers.NestedSimpleRouter(router, r"shows", lookup="show")
 
 # /shows/1/schedules
-show_router.register(r'schedules', APIScheduleViewSet, basename='show-schedules')
+show_router.register(r"schedules", APIScheduleViewSet, basename="show-schedules")
 
 # /shows/1/notes
-show_router.register(r'notes', APINoteViewSet, basename='show-notes')
+show_router.register(r"notes", APINoteViewSet, basename="show-notes")
 
 # /shows/1/timeslots
-show_router.register(r'timeslots', APITimeSlotViewSet, basename='show-timeslots')
-show_timeslot_router = routers.NestedSimpleRouter(show_router, r'timeslots', lookup='timeslot')
+show_router.register(r"timeslots", APITimeSlotViewSet, basename="show-timeslots")
+show_timeslot_router = routers.NestedSimpleRouter(
+    show_router, r"timeslots", lookup="timeslot"
+)
 
 # /shows/1/timeslots/1/note/
-show_timeslot_router.register(r'note', APINoteViewSet, basename='show-timeslots-note')
+show_timeslot_router.register(r"note", APINoteViewSet, basename="show-timeslots-note")
 
 # /shows/1/schedules
-schedule_router = routers.NestedSimpleRouter(show_router, r'schedules', lookup='schedule')
+schedule_router = routers.NestedSimpleRouter(
+    show_router, r"schedules", lookup="schedule"
+)
 
 # /shows/1/schedules/1/timeslots
-schedule_router.register(r'timeslots', APITimeSlotViewSet, basename='schedule-timeslots')
-timeslot_router = routers.NestedSimpleRouter(schedule_router, r'timeslots', lookup='timeslot')
+schedule_router.register(
+    r"timeslots", APITimeSlotViewSet, basename="schedule-timeslots"
+)
+timeslot_router = routers.NestedSimpleRouter(
+    schedule_router, r"timeslots", lookup="timeslot"
+)
 
 # /shows/1/schedules/1/timeslots/1/note
-timeslot_router.register(r'note', APINoteViewSet, basename='timeslots-note')
+timeslot_router.register(r"note", APINoteViewSet, basename="timeslots-note")
 
 urlpatterns = [
-    path('openid/', include('oidc_provider.urls', namespace='oidc_provider')),
-    path('api/v1/', include(router.urls)),
-    path('api/v1/', include(show_router.urls)),
-    path('api/v1/', include(show_timeslot_router.urls)),
-    path('api/v1/', include(schedule_router.urls)),
-    path('api/v1/', include(timeslot_router.urls)),
-    path('api/v1/playout', json_playout),
-    path('api/v1/program/week', json_playout),
-    path('api/v1/program/<int:year>/<int:month>/<int:day>)/', json_day_schedule),
-    path('admin/', admin.site.urls),
+    path("openid/", include("oidc_provider.urls", namespace="oidc_provider")),
+    path("api/v1/", include(router.urls)),
+    path("api/v1/", include(show_router.urls)),
+    path("api/v1/", include(show_timeslot_router.urls)),
+    path("api/v1/", include(schedule_router.urls)),
+    path("api/v1/", include(timeslot_router.urls)),
+    path("api/v1/playout", json_playout),
+    path("api/v1/program/week", json_playout),
+    path("api/v1/program/<int:year>/<int:month>/<int:day>)/", json_day_schedule),
+    path("admin/", admin.site.urls),
 ]
diff --git a/steering/wsgi.py b/steering/wsgi.py
index 7c83fe0c815e9c0dd96b815a90e35b328c2fe7fb..89cf86942c455b389498fd99ce5f2cea7c21c494 100644
--- a/steering/wsgi.py
+++ b/steering/wsgi.py
@@ -1,33 +1,16 @@
-# -*- coding: utf-8 -*-
-
 """
-WSGI config for pv project.
-
-This module contains the WSGI application used by Django's development server
-and any production WSGI deployments. It should expose a module-level variable
-named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
-this application via the ``WSGI_APPLICATION`` setting.
+WSGI config for alias project.
 
-Usually you will have the standard Django WSGI application here, but it also
-might make sense to replace the whole Django WSGI application with a custom one
-that later delegates to the Django one. For example, you could introduce WSGI
-middleware here, or combine a Django application with an application of another
-framework.
+It exposes the WSGI callable as a module-level variable named ``application``.
 
+For more information on this file, see
+https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
 """
+
 import os
-import sys
 
-sys.path.append('/srv/pv/pv')
+from django.core.wsgi import get_wsgi_application
 
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "steering.settings")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alias.settings")
 
-# This application object is used by any WSGI server configured to use this
-# file. This includes Django's development server, if the WSGI_APPLICATION
-# setting points here.
-from django.core.wsgi import get_wsgi_application
 application = get_wsgi_application()
-
-# Apply WSGI middleware here.
-# from helloworld.wsgi import HelloWorldApplication
-# application = HelloWorldApplication(application)