Django: Проблема с удалением объектов базы данных "многие-ко-многим", когда они связаны со сквозной таблицей
Django выдает ошибку, что я не могу удалить объект composer, который раньше был связан с объектом spotifyartist через пользовательскую сквозную таблицу. Мое приложение Django называется 'music', и я использую mysql/mariadb в качестве базы данных
При удалении объекта composer Django выдает следующую ошибку: IntegrityError at /admin/music/composer/(1451, 'Cannot delete or update a parent row: a foreign key constraint fails (bladmuziek
.music_composer_spot_artist
, CONSTRAINT music_composer_spot__composer_id_4d30a8de_fk_music_com
FOREIGN KEY (composer_id
) REFERENCES music_composer
(id
))')
Даже после удаления записи в сквозной таблице для пары композитор + исполнитель Spotify, когда между двумя объектами модели больше нет очевидной связи (для меня), я все равно не могу удалить (ранее связанный) объект композитора или исполнителя Spotify.
Я не могу понять, как я нарушаю ограничение, о котором говорит сообщение об ошибке. Думаю, я не до конца понимаю сообщение об ошибке и не знаю точно, связано ли оно с ограничением, которое я добавил в сквозную модель, или это какое-то другое ограничение. Любые предложения о том, как полностью понять сообщение об ошибке и удалить объект Django, будут приняты с благодарностью. Соответствующие фрагменты моего кода - это модель composer, модель spotifyartist и сквозная таблица ComposerSpotLink, которая предназначена для отслеживания типа отношений между композитором и spot-artist. Эта таблица имеет пользовательское ограничение:
class Composer(models.Model):
first_name = models.CharField(max_length = 50, blank = True)
last_name = models.CharField(max_length = 50)
birth_year = models.SmallIntegerField(default = 0)
death_year = models.SmallIntegerField(default = 0)
spot_artist = models.ManyToManyField('SpotifyArtist', through = 'ComposerSpotLink', related_name = 'composer', blank = True)
class SpotifyArtist(models.Model):
spot_id = models.CharField(validators = [validate_spot_id], max_length = 22, unique = True) #spot_id: is the unique base-62 identifier from Spotify
spot_name = models.CharField(max_length = 255)
class Type(models.IntegerChoices):
PRIMARY = 1, _("Primary")
SECONDARY = 2, _("Secondary")
IGNORE = 3, _("Ignore")
UNVERIFIED = 4, _("Unverified")
class ComposerSpotLink(models.Model):
"""Through model for the relationship between database composer and spotify Artist."""
composer = models.ForeignKey('Composer', on_delete = models.CASCADE, related_name = 'composerspotlink')
spot_artist= models.ForeignKey('SpotifyArtist', on_delete = models.CASCADE, related_name = 'composerspotlink')
type = models.IntegerField(choices = Type.choices, default = Type.UNVERIFIED)
def clean(self):
if self.type == Type.PRIMARY and ComposerSpotLink.objects.filter(composer = self.composer, \
type = Type.PRIMARY).exclude(spot_artist = self.spot_artist).exists():
sa = SpotifyArtist.objects.get(composerspotlink__composer = self.composer, composerspotlink__type = Type.PRIMARY)
raise ValidationError(_(f'{self.composer} already has a primary spotify artist assigned: {sa}'),
code = 'Integrity error: only one primary spotify artist per composer',
params = {'composer': self.composer},)
class Meta:
order_with_respect_to = 'composer'
constraints = [ UniqueConstraint(fields = ['composer','spot_artist'], name = "spotify_relationship")]
def save(self, *args, **kwargs):
self.clean()
super(ComposerSpotLink, self).save(*args, **kwargs)