xintron
xintron

Reputation: 326

Override delete-function on multi-delete

The following works great when going to the objects adminpage and select delete. The problem is that when using multiselect and deleting multiple items at once it doesn't use my delete-override. I've been looking for a solution but haven't found one so it's time to turn to the masters ;)

class Photo(models.Model):
    name = models.CharField(max_length=256, unique=True)
    slug = models.SlugField(unique=True)
    image = models.ImageField(upload_to='photos/')

    def delete(self):
        super(Photo, self).delete()
        ### Check if the dir is empty, then remove the folder
        ph = Photo.objects.filter(album=self.album)
        if ph.count() == 0:
            rmtree(os.path.join(settings.MEDIA_ROOT, 'photos/' + self.album.slug))     

Upvotes: 0

Views: 1431

Answers (3)

TooDiesel
TooDiesel

Reputation: 71

Just for completeness, the model's delete method isn't called on a Model.objects.filter(...).delete() call: https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.delete

Django sends two signals, pre_delete and post_delete, after a Model.objects.filter(...).delete() call. More info here: https://docs.djangoproject.com/en/dev/ref/signals/#pre-delete

Upvotes: 1

xintron
xintron

Reputation: 326

Solved my problem :)

class PhotoQuerySet(QuerySet):
    def delete(self):
        for x in self:
            x.delete()

class PhotoManager(models.Manager):
    def get_query_set(self):
        return PhotoQuerySet(self.model)

class Photo(models.Model):
    name = models.CharField(max_length=256, unique=True)
    slug = models.SlugField(unique=True)
    image = models.ImageField(upload_to='photos/')

    objects = PhotoManager()

    def delete(self):
        os.remove(self.get_thumbnail_name())
        os.remove(self.get_medium_name())
        super(Photo, self).delete()

Upvotes: 3

brianz
brianz

Reputation: 7448

when using multiselect and deleting multiple items at once

I suspect this means you're doing something like:

Photo.objects.filter(name='something').delete()

If that's the case, that will not call your custom delete method since it uses the delete method on a queryset. While not very efficient, you can force your delete method to be called by:

for photo in Photo.objects.filter(name='something'):
    photo.delete()

Upvotes: 0

Related Questions