¿Cómo sobrescribo delete () en un modelo y todavía funciona con eliminaciones relacionadas?

Tengo un problema porque estoy eliminando un Widget utilizando some_widget_instance.delete (). También tengo un modelo llamado WidgetFile con un método de eliminación de cancelación () para poder eliminar archivos de mi disco duro cuando se elimina un WidgetFile. El problema que tengo es que si elimino un Widget, y tiene WidgetFiles relacionados con esto como esto:

class WidgetFile(models.Model): widget = models.ForeignKey(Widget) 

Bueno, cuando elimino ese Widget, se eliminan los WidgetFiles, pero el método delete () no se activa y hace mi disco duro adicional. Cualquier ayuda es muy apreciada.

Estoy haciendo lo mismo y noté un nugget en la documentación de Django en el que deberías pensar.

Anulación de métodos de modelo predefinidos

Anulación de la eliminación Tenga en cuenta que el método delete () para un objeto no se llama necesariamente cuando se eliminan objetos de forma masiva utilizando un QuerySet. Para garantizar que la lógica de eliminación personalizada se ejecute, puede usar señales pre_delete y / o post_delete.

Esto significa que tu fragmento no siempre hará lo que quieres. Usar señales es una mejor opción para lidiar con las eliminaciones.

Fui con lo siguiente:

 import shutil from django.db.models.signals import pre_delete from django.dispatch import receiver @receiver(pre_delete) def delete_repo(sender, instance, **kwargs): if sender == Set: shutil.rmtree(instance.repo) 

Me lo imaginé. Acabo de poner esto en ese modelo de Widget:

 def delete(self): files = WidgetFile.objects.filter(widget=self) if files: for file in files: file.delete() super(Widget, self).delete() 

Esto activó el método delete () necesario en cada uno de los objetos relacionados, activando así mi código de eliminación de archivos personalizado. Es más caro en la base de datos, sí, pero cuando intenta eliminar archivos en un disco duro de todos modos, no es un gasto tan grande golpear el db unas cuantas veces más.

Al usar clear() antes de eliminar, elimina todos los objetos del conjunto de objetos relacionados.

ver django-following-relationships-backward

ejemplo:

 group.link_set.clear() group.delete() 

Esto solo parece tener sentido si un Widget está conectado a un WidgetFile exactamente. En ese caso debes usar un OneToOneField

de ejemplos uno a uno:

 # Delete the restaurant; the waiter should also be removed >>> r = Restaurant.objects.get(pk=1) >>> r.delete() 

Solo para solucionar de una manera posible este problema: la señal de eliminación previa . (De ninguna manera implica que no hay una solución real).

Debería verse como se describe en el sitio de django :

 class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): do_something() super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else() 

http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

olvidaste pasar algunos argumentos

¿Es some_widget_instance y una instancia de Widget o de WidgetFile ? Porque si es una instancia de Widget , no obtendrá su función personalizada delete() , que se encuentra en la clase WidgetFile .

Desde Django 1.9, si solo definiría on_delete=models.CASCADE para el campo, eliminará todos los objetos relacionados al eliminar.