I'm creating a reusable django app which includes a model with GenericForeignKey
which I need to be cascade deleted.
This model may be attached to any other. I have no control over target model class as it is outside of the app. This means I can not add GenericRelation
field to it and can't force user to add it as target might be in another third-party app.
Assuming we have such models (having NO control over Post
and PostGroup
):
class Tag(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
object = GenericForeignKey()
class PostGroup(models.Model):
title = models.CharField(max_length=255)
class Post(models.Model):
title = models.CharField(max_length=255)
group = models.ForeignKey(PostGroup, on_delete=models.CASCADE)
Is there a way to delete Tag
in case of PostGroup
queryset is being deleted?
E.g. not only post_group.delete()
but also PostGroup.objects.delete()
.
You can use pre_delete
signal to achieve this:
from django.db.models.signals import pre_delete
from django.dispatch import receiver
@receiver(pre_delete) # add relevant sender to signal (not mandatory)
def post_group_deleted(sender, instance, using, **kwargs):
# Query tags with the instance of PostGroup and delete them
if isinstance(instance, Tag):
return
Tag.objects.filter(
content_type=ContentType.objects.get_for_model(instance),
object_id=instance.pk
).delete()
See documentation here
Unlike ForeignKey, GenericForeignKey does not accept an on_delete argument to customize this behavior; if desired, you can avoid the cascade-deletion by not using GenericRelation, and alternate behavior can be provided via the pre_delete signal.