SpellTheif
SpellTheif

Reputation: 715

Django - override save method

I'm overriding the save() method for a model in Django, but it's not working properly.

I want the book_quantity to update automatically each time when, I edit the number of books in a cart and click save button.

For instance:

I've already changed the number of the book from 0 to 11 and clicked the save button, but the book_quantity still showing number 0 (the previous number). If I change the number from 11 to 22 or not change the number then click the save button again. The book_quantity will be 11. So it always shows the previous number. But what I want is that the book_quantity changes to the correct number immediately each time when I click the save button (once).

enter image description here

cart/models.py

class Cart(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
    book_quantity = models.IntegerField(default=0)
    total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0)

    def __str__(self):
        return self.user.email + '_cart'

    def save(self, *args, **kwargs):
        self.book_quantity = 0
        books = BooksInCart.objects.filter(cart__user=self.user).values('quantity')
        for i in range(len(books)):
            self.book_quantity += books[i].get('quantity')
        super().save(*args, **kwargs)


class BooksInCart(models.Model):

    cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)


    def __str__(self):
        return self.book.title

Edit:

Why am I doing this it because I want the book_quantityand total_price update each time when I add a BooksInCart instance into the cart or edit/delete a BooksInCart from the cart. But extending the save() method is the only idea I came up with. Is there any other better way to achieve this?

Upvotes: 1

Views: 1937

Answers (1)

Henry
Henry

Reputation: 176

Well, I not sure about your idea but,

maybe you can try to use signal? everytime when your quantity is changed, it will change the book_quantity. Such as:

from django.db.models.signals import post_save

@receiver(post_save, sender=BooksInCart) # the sender is your fix
def update_book_quantity(sender, instance, **kwargs):
    book_quantity = 0
    books = BooksInCart.objects.filter(cart=instance.cart).values('quantity')
    for item in book.iterator():
        book_quantity += item.get('quantity')
    instance.update(book_quantity=book_quantity)
    # TODO

Meanwhile, I agree with such things don't need to be stored in the database.

Frankly speaking, this design is awful and it will case problem when the service is used by many people.

So why not try saving it in cache (try it maybe) or try another solution of your design?

Upvotes: 1

Related Questions