Say I have a model with a Things
table and a table of relationships between the things called ThingRelations
. It should not be possible to delete a Thing
when there are ThingRelations
that point to it, and when there are no more ThingRelations
pointing to a given Thing
, it should be deleted. I'm currently trying to implement that with signals.post_delete
like this:
from django.db import models
class ThingRelation(models.Model):
first_thing = models.ForeignKey('Thing', on_delete=models.PROTECT)
second_thing = models.ForeignKey('Thing', on_delete=models.PROTECT)
class Thing(models.Model):
name = CharField(max_length=260)
@receiver(models.signals.post_delete, sender=ThingRelation)
def check_relation_and_delete(sender, instance, *args, **kwargs):
for thing_id in [instance.first_thing, instance.second_thing]:
first_thing_match = ThingRelation.objects.filter(first_thing=thing_id).exists()
second_thing_match = ThingRelation.objects.filter(second_thing=thing_id).exists()
if not first_thing_match and not second_thing_match:
Thing.objects.get(pk=thing_id).delete()
Is this the most efficient way to find and delete orphaned Things
? I'm very new to databases in general, but won't filtering the (potentially quite large) Things
table four times for every deleted ThingRelation
be slow when deleting many objects at once? Is there some kind of SQL or Django functionality that makes it so this code isn't run for every object in a bulk operation?