Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

384
Vistas
¿Cuál es la forma más eficiente de verificar si hay huérfanos al eliminar objetos en Django?

Digamos que tengo un modelo con una tabla Things y una tabla de relaciones entre las cosas llamada ThingRelations . No debería ser posible eliminar una Thing cuando hay ThingRelations que apuntan a ella, y cuando no hay más ThingRelations que apuntan a una Thing determinada, debe eliminarse. Actualmente estoy tratando de implementar eso con signals.post_delete así:

 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()

¿Es esta la forma más eficiente de encontrar y eliminar Things huérfanas? Soy muy nuevo en las bases de datos en general, pero ¿no será lento filtrar la tabla Things (potencialmente bastante grande) cuatro veces por cada ThingRelation eliminada al eliminar muchos objetos a la vez? ¿Existe algún tipo de funcionalidad SQL o Django que haga que este código no se ejecute para cada objeto en una operación masiva?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

signals.py no está diseñado para operaciones masivas . Además, a menudo se los considera un antipatrón , debido a la dificultad de rastrearlos cuando se intenta depurar alguna lógica.

Prefiero aconsejarle que pruebe el enfoque de rutina aquí. Un ejemplo, que te puede ser útil:

 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()

Esta función elimina todas las cosas Thing . Así que todo lo que queda es que necesitamos llamarlo correctamente.

La forma más fácil y directa es organizarlo en una rutina interminable while-true sleep y ejecutarlo como un demonio. Por ejemplo:

 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)

Por lo tanto, se ejecutaría casi una vez cada 5 minutos. Podría ejecutarse con algo como supervisor (mejor) o tmux (peor), para que pueda estar seguro de que siempre se está ejecutando.

La mejor manera es usar algo como periodic para orquestarlo. Aquí hay una guía de instalación (también necesitaría RabbitMQ) y un pequeño ejemplo de cómo organizarlo:

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

¡Buena suerte!

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda