Each Answer to this Q is separated by one/two green lines.
I’m having a problem because I’m deleting a Widget by using some_widget_instance.delete(). I also have a model called WidgetFile with an override delete() method so that I can delete files off my hard drive when a WidgetFile is deleted. The problem I’m having is that if I delete a Widget, and it has WidgetFiles related to it like this:
class WidgetFile(models.Model): widget = models.ForeignKey(Widget)
Well, when I delete that Widget, it’s WidgetFiles are deleted but the delete() method doesn’t trigger and do my extra hard drive stuff. Any help is much appreciated.
I’m doing the same thing and noticed a nugget in the Django docs that you should think about.
Note that the delete() method for an object is not necessarily called when deleting objects in bulk using a QuerySet. To ensure customized delete logic gets executed, you can use pre_delete and/or post_delete signals.
This means your snippet will not always do what you want. Using Signals is a better option for dealing with deletions.
I went with the following:
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)
I figured it out. I just put this on that Widget model:
def delete(self): files = WidgetFile.objects.filter(widget=self) if files: for file in files: file.delete() super(Widget, self).delete()
This triggered the necessary delete() method on each of the related objects, thus triggering my custom file deleting code. It’s more database expensive yes, but when you’re trying to delete files on a hard drive anyway, it’s not such a big expense to hit the db a few extra times.
clear() prior to deleting, removes all objects from the related object set.
It should look like described on the django site:
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()
you forgot to pass some arguments
some_widget_instance and instance of
Widget or of
WidgetFile ? Because if it is an instance of
Widget it won’t get your custom
delete() function, which is in the
From Django 1.9, if You would just define
on_delete=models.CASCADE for field, it will remove all related objects on delete.