Django en cascada eliminar en claves externas inversas

Django muestra cómo configurar o anular las eliminaciones en cascada con claves externas en sus documentos.

model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL) 

Pero ¿y si quisiéramos este efecto al revés? ¿Qué sucede si queremos que la eliminación del modelo fk dé como resultado la eliminación de este modelo?

Gracias

Hay un punto de implementación muy delicado, que pensé que debería agregar a esta discusión.

Digamos que tenemos dos modelos, uno de los cuales hace referencia al otro mediante una clave externa, como en:

 class A(models.Model): x = models.IntegerField() class B(models.Model): a = models.ForeignKey(A, null=True, blank=True) 

Ahora, si eliminamos una entrada de A, el comportamiento en cascada causará que la referencia en B también se elimine.

Hasta ahora tan bueno. Ahora queremos revertir este comportamiento. La forma obvia como la gente ha mencionado es usar las señales emitidas durante la eliminación, así que vamos:

 def delete_reverse(sender, **kwargs): if kwargs['instance'].a: kwargs['instance'].a.delete() post_delete.connect(delete_reverse, sender=B) 

Esto parece ser perfecto. ¡Incluso funciona! Si borramos una entrada B, también se eliminará la A correspondiente.

El PROBLEMA es que tiene un comportamiento circular que provoca una excepción: si eliminamos un elemento de A, debido al comportamiento en cascada predeterminado (que queremos mantener), el elemento correspondiente de B también se eliminará, lo que provocará delete_reverse a ser llamado, que intenta eliminar un elemento ya eliminado!

El truco es que necesita MANEJO DE EXCEPCIONES para la implementación correcta de la cascada inversa:

 def delete_reverse(sender, **kwargs): try: if kwargs['instance'].a: kwargs['instance'].a.delete() except: pass 

Este código funcionará de cualquier manera. Espero que ayude a algunas personas.

No creo que la característica que está viendo sea un concepto ORM o de base de datos. Solo desea ejecutar una callback cuando se borra algo.

Así que use la señal post_delete y agregue su controlador de callback allí

 from django.db.models.signals import post_delete from django.dispatch import receiver from myapp.models import MyModel @receiver(post_delete, sender=MyModel) def my_post_delete_callback(sender, **kwargs): #Sender is the model which when deleted should trigger this action #Do stuff like delete other things you want to delete #The object just deleted can be accessed as kwargs[instance]