Reputation: 3381
Imagine PetOwner
and a Pet
models:
class PetOwner(models.Model):
name = models.CharField()
class Pet(models.Model):
owner = models.ForeignKey('PetOwner', on_delete=models.CASCADE)
alive = models.BooleanField(default=True)
I would like it to be possible to delete PetOwners, but only if all theiry associated Pets are not alive anymore. If that is the case, the PetOwner can be deleted and all his associated pets are also deleted (cascade semantics).
Is that possible?
Upvotes: 0
Views: 51
Reputation: 51685
You are talking about to set a 'business rule'. You can write your 'business rules' in several places, for example, in each view or process that delete PetOwners
.
Also, you can override delete
method on model. Take in mind:
Overridden model methods are not called on bulk operations
Note that the delete() method for an object is not necessarily called when deleting objects in bulk using a QuerySet or as a result of a cascading delete. To ensure customized delete logic gets executed, you can use pre_delete and/or post_delete signals.
This is how to override 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()
Another solution are signals:
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")
Upvotes: 1