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)