From b8c4ecd76093a0fe4e22bec23f4e76185f54a6f7 Mon Sep 17 00:00:00 2001 From: Ernesto Rico Schmidt <ernesto@helsinki.at> Date: Thu, 1 Aug 2024 20:01:47 -0400 Subject: [PATCH] fix: make some foreign keys nullable & on_delete=SET_NULL to avoid delete cascade --- ...note_image_alter_notelink_type_and_more.py | 173 ++++++++++++++++++ program/models.py | 31 ++-- 2 files changed, 191 insertions(+), 13 deletions(-) create mode 100644 program/migrations/0116_alter_note_image_alter_notelink_type_and_more.py diff --git a/program/migrations/0116_alter_note_image_alter_notelink_type_and_more.py b/program/migrations/0116_alter_note_image_alter_notelink_type_and_more.py new file mode 100644 index 00000000..efed7fe0 --- /dev/null +++ b/program/migrations/0116_alter_note_image_alter_notelink_type_and_more.py @@ -0,0 +1,173 @@ +# Generated by Django 4.2.14 on 2024-08-01 22:26 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("program", "0115_alter_note_options_alter_schedule_options_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="note", + name="image", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="notes", + to="program.image", + ), + ), + migrations.AlterField( + model_name="notelink", + name="type", + field=models.ForeignKey( + default=1, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="program.linktype", + ), + ), + migrations.AlterField( + model_name="profile", + name="image", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="profiles", + to="program.image", + ), + ), + migrations.AlterField( + model_name="profilelink", + name="type", + field=models.ForeignKey( + default=1, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="program.linktype", + ), + ), + migrations.AlterField( + model_name="radiosettings", + name="fallback_show", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="program.show", + ), + ), + migrations.AlterField( + model_name="radiosettings", + name="micro_show", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="program.show", + ), + ), + migrations.AlterField( + model_name="schedule", + name="rrule", + field=models.ForeignKey( + help_text="A recurrence rule.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="schedules", + to="program.rrule", + ), + ), + migrations.AlterField( + model_name="schedule", + name="show", + field=models.ForeignKey( + help_text="Show the schedule belongs to.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="schedules", + to="program.show", + ), + ), + migrations.AlterField( + model_name="show", + name="funding_category", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="shows", + to="program.fundingcategory", + ), + ), + migrations.AlterField( + model_name="show", + name="image", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="shows", + to="program.image", + ), + ), + migrations.AlterField( + model_name="show", + name="logo", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="logo_shows", + to="program.image", + ), + ), + migrations.AlterField( + model_name="show", + name="predecessor", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="successors", + to="program.show", + ), + ), + migrations.AlterField( + model_name="show", + name="type", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="shows", + to="program.type", + ), + ), + migrations.AlterField( + model_name="showlink", + name="type", + field=models.ForeignKey( + default=1, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="program.linktype", + ), + ), + migrations.AlterField( + model_name="timeslot", + name="repetition_of", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="repetitions", + to="program.timeslot", + ), + ), + ] diff --git a/program/models.py b/program/models.py index 17b7ac18..e8e32fcd 100644 --- a/program/models.py +++ b/program/models.py @@ -174,7 +174,7 @@ class Profile(models.Model): created_at = models.DateTimeField(auto_now_add=True) created_by = models.CharField(max_length=150) email = models.EmailField(blank=True, help_text="Email address of the profile.") - image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="profiles") + image = models.ForeignKey(Image, null=True, on_delete=models.SET_NULL, related_name="profiles") is_active = models.BooleanField(default=True, help_text="True if the profile is active.") name = models.CharField(max_length=128, help_text="Display name of the profile.") owners = models.ManyToManyField( @@ -212,7 +212,7 @@ class LinkType(models.Model): class Link(models.Model): - type = models.ForeignKey(LinkType, default=1, on_delete=models.CASCADE) + type = models.ForeignKey(LinkType, default=1, null=True, on_delete=models.SET_NULL) url = models.URLField() class Meta: @@ -242,23 +242,23 @@ class Show(models.Model): description = models.TextField(blank=True, help_text="Description of this show.") email = models.EmailField(blank=True, null=True, help_text="Email address of this show.") funding_category = models.ForeignKey( - FundingCategory, blank=True, null=True, on_delete=models.CASCADE, related_name="shows" + FundingCategory, blank=True, null=True, on_delete=models.SET_NULL, related_name="shows" ) hosts = models.ManyToManyField(Profile, blank=True, related_name="shows") - image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="shows") + image = models.ForeignKey(Image, null=True, on_delete=models.SET_NULL, related_name="shows") internal_note = models.TextField(blank=True, help_text="Internal note for this show.") is_active = models.BooleanField(default=True, help_text="True if this show is active.") is_public = models.BooleanField(default=False, help_text="True if this show is public.") language = models.ManyToManyField(Language, blank=True, related_name="shows") # TODO: is this really necessary? logo = models.ForeignKey( - Image, blank=True, null=True, on_delete=models.CASCADE, related_name="logo_shows" + Image, blank=True, null=True, on_delete=models.SET_NULL, related_name="logo_shows" ) music_focus = models.ManyToManyField(MusicFocus, blank=True, related_name="shows") name = models.CharField(max_length=255, help_text="Name of this Show.") owners = models.ManyToManyField(User, blank=True, related_name="shows") predecessor = models.ForeignKey( - "self", blank=True, null=True, on_delete=models.CASCADE, related_name="successors" + "self", blank=True, null=True, on_delete=models.SET_NULL, related_name="successors" ) short_description = models.TextField(help_text="Short description of this show.") slug = models.SlugField( @@ -266,7 +266,7 @@ class Show(models.Model): ) topic = models.ManyToManyField(Topic, blank=True, related_name="shows") type = models.ForeignKey( - Type, blank=True, null=True, on_delete=models.CASCADE, related_name="shows" + Type, blank=True, null=True, on_delete=models.SET_NULL, related_name="shows" ) updated_at = models.DateTimeField(auto_now=True, blank=True, null=True) updated_by = models.CharField(blank=True, default="", max_length=150) @@ -417,12 +417,17 @@ class Schedule(models.Model): ) last_date = models.DateField(help_text="End date of schedule.", null=True) rrule = models.ForeignKey( - RRule, help_text="A recurrence rule.", on_delete=models.CASCADE, related_name="schedules" + RRule, + help_text="A recurrence rule.", + null=True, + on_delete=models.SET_NULL, + related_name="schedules", ) show = models.ForeignKey( Show, help_text="Show the schedule belongs to.", - on_delete=models.CASCADE, + null=True, + on_delete=models.SET_NULL, related_name="schedules", ) start_time = models.TimeField(help_text="Start time of schedule.") @@ -448,7 +453,7 @@ class TimeSlot(models.Model): memo = models.TextField(blank=True, help_text="Memo for this timeslot.") playlist_id = models.IntegerField(null=True, help_text="Playlist ID of this timeslot.") repetition_of = models.ForeignKey( - "self", blank=True, null=True, on_delete=models.CASCADE, related_name="repetitions" + "self", blank=True, null=True, on_delete=models.SET_NULL, related_name="repetitions" ) schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE, related_name="timeslots") start = models.DateTimeField() @@ -495,7 +500,7 @@ class Note(models.Model): ) created_at = models.DateTimeField(auto_now_add=True) created_by = models.CharField(max_length=150) - image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE, related_name="notes") + image = models.ForeignKey(Image, null=True, on_delete=models.SET_NULL, related_name="notes") language = models.ManyToManyField(Language, blank=True, related_name="episodes") playlist = models.TextField(blank=True) summary = models.TextField(blank=True, help_text="Summary of the Note.") @@ -650,7 +655,7 @@ class RadioSettings(models.Model): blank=True, max_length=32, validators=[validate_fallback_default_pool] ) fallback_show = models.ForeignKey( - Show, blank=True, null=True, on_delete=models.CASCADE, related_name="+" + Show, blank=True, null=True, on_delete=models.SET_NULL, related_name="+" ) line_in_channels = models.JSONField( blank=True, @@ -659,7 +664,7 @@ class RadioSettings(models.Model): validators=[validate_line_in_channels], ) micro_show = models.ForeignKey( - Show, blank=True, null=True, on_delete=models.CASCADE, related_name="+" + Show, blank=True, null=True, on_delete=models.SET_NULL, related_name="+" ) note_image_aspect_ratio = ImageAspectRadioField(default="16:9") note_image_shape = ImageShapeField(default="rect") -- GitLab