我可以防止 Django 根据引用类型中的属性删除对象吗?
Can I prevent Django from deleting an object depending on an attribute in a referencing type?
想象一下 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,但前提是他们的所有相关宠物都不再活着。如果是这样,则可以删除 PetOwner,同时删除他所有关联的宠物(级联语义)。
这可能吗?
您正在谈论设置 'business rule'。您可以在多个地方写下您的 'business rules',例如,在删除 PetOwners
.
的每个视图或进程中
此外,您可以在模型上使用 override delete
方法。请记住:
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.
这是覆盖删除的方法:
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()
另一个解决方案是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")
想象一下 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,但前提是他们的所有相关宠物都不再活着。如果是这样,则可以删除 PetOwner,同时删除他所有关联的宠物(级联语义)。
这可能吗?
您正在谈论设置 'business rule'。您可以在多个地方写下您的 'business rules',例如,在删除 PetOwners
.
此外,您可以在模型上使用 override delete
方法。请记住:
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.
这是覆盖删除的方法:
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()
另一个解决方案是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")