Могу ли я запретить Django удалять объект в зависимости от атрибута в ссылающемся типе?
Представьте PetOwner и Pet модели:
class PetOwner(models.Model):
name = models.CharField()
class Pet(models.Model):
owner = models.ForeignKey('PetOwner', on_delete=models.CASCADE)
alive = models.BooleanField(default=True)
Я бы хотел, чтобы можно было удалять владельцев питомцев, но только если все связанные с ними питомцы больше не живы. В этом случае владелец питомца может быть удален, и все связанные с ним питомцы также будут удалены (каскадная семантика).
Возможно ли это?
Вы говорите о том, чтобы установить "бизнес-правило". Вы можете написать свои "бизнес-правила" в нескольких местах, например, в каждом представлении или процессе, который удаляет PetOwners.
Также вы можете переопределить delete метод на модели. Имейте в виду:
Преодоленные методы модели не вызываются при массовых операциях
Обратите внимание, что метод delete() для объекта не обязательно вызывается при массовом удалении объектов с помощью QuerySet или в результате каскадного удаления. Чтобы гарантировать выполнение настроенной логики удаления, вы можете использовать сигналы pre_delete и/или post_delete.
.
Вот как отменить удаление:
from django.core.exceptions import PermissionDenied
class PetOwner(models.Model):
# ...
def delete(self):
has_pets_alive = self.pet_set.filter(alive=True).exists()
if has_pets_alive:
raise PermissionDenied("This owner has pets alive")
super(PetOwner, self).delete()
Другим решением являются сигналы:
from django.db.models.signals import pre_delete
from django.dispatch import receiver
@receiver(pre_delete, sender=PetOwner)
def check_pets_alive(sender, instance, **kwargs):
has_pets_alive = instance.pet_set.filter(alive=True).exists()
if has_pets_alive:
raise PermissionDenied("This owner has pets alive")