Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

378
Visualizações
what's the most efficient way to check for orphans when deleting objects in Django?

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?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

signals.py is not designed for bulk operations. Also they are often considered an anti-pattern, because of difficulty of traceability them when you trying to debug some logic.

I'd rather advise you to try routine approach here. An example, which might be helpful for you:

def remove_orphaned_things():
    orphaned_things = Thing.objects.filter(
        ~Q(id__in=ThingRelation.objects.values_list('first_thing_id').filter(
            first_thing_id=OuterRef('pk')
        ) | ~Q(id__in=ThingRelation.objects.values_list('second_thing_id').filter(
            second_thing_id=OuterRef('pk')
        )
    ).delete()

This function removes all orphaned Thing's. So all that left is we need to call it properly.

The most easy and straightforward way is to organise it to endless while-true routine with some sleep and run it as a daemon. For example:

from datetime import time
from django.core.management import BaseCommand
# Also some import of `remove_orphaned_things`

class Command(BaseCommand):
    def handle(self, *args, **options):
        while True:
            remove_orphaned_things()
            time.sleep(300)

So it would be executed nearly once per 5 minutes. It could be run with something like supervisor (better) or tmux (worse), so you can be sure it's always running.

The better way is to use something like periodic to orchestrate it. Here is an installation guide (you'd also need RabbitMQ) and a little example how to organise it:

@dramatiq.actor(periodic=cron('*/5 * * * *'), max_retries=0)
def remove_orphaned_things():
    # Exact the same code of `remove_orphaned_things`

Good luck!

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda