Damoiskii
Damoiskii

Reputation: 1370

Django model delete method not overriding

I'm currently working on a Django blog app where I have a Post connecting to a Category. The Category has both name and times_used fields. times_used will be incremented by 1 after a Post is created and I have achieved this overriding the save() method on the Post model. I'm trying to override the delete() method to decrement the current post's category by 1 but it's not actually reaching the overridden delete() method it seems, because the category still has the incremented value even after the post got deleted. See my code below...

model.py

class Category(models.Model):
    name = models.CharField(max_length=150, unique=True)
    times_used = models.IntegerField(default=0)


class Post(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    # This increments this category by 1 then saves the post - Works well!
    def save(self, *args, **kwargs):
        self.category.times_used += 1
        self.category.save()

        super(Post, self).save(*args, **kwargs)

    # This decrements this category by 1 then deletes the post - Which is not working...
    def delete(self, *args, **kwargs):
        self.category.times_used -= 1
        self.category.save()

        super(Post, self).delete(*args, **kwargs)

Any suggestions how to accomplish this?

Upvotes: 1

Views: 3238

Answers (2)

Damoiskii
Damoiskii

Reputation: 1370

I read about Django signals just now and have accomplished what I wanted to. According to the Django documentation... the delete() method doesn't get called when we override it to delete objects in bulk using a QuerySet. So it's best to use a signal to get these types of job done.

In my models.py I've pass the Post as an argument to a function which I have a created in signals.py

models.py

class Post(models.Model):
    ....

delete_post_signal(Post)

Within my signals.py I have the following code...

from django.dispatch import receiver
from django.db.models.signals import pre_delete


def delete_post_signal(Post):

    @receiver(pre_delete, sender=Post)
    def decrement_category_usage(sender, instance, **kwargs):
        instance.category.times_used -= 1
        instance.category.save()

This worked for me perfectly...

Upvotes: 3

Viktor Mironov
Viktor Mironov

Reputation: 163

You can do it with pre_delete signal like this

@receiver(pre_delete, sender=Post)
def my_handler(sender, instance, **kwargs):
    instance.category.times_used -= 1
    instance.category.save()

Upvotes: 0

Related Questions