dewDevil
dewDevil

Reputation: 391

Updating Cart in Django Admin on adding and removing items

I have the following models in my application in which I add items to a cart and can remove them too. The adding and removing of a cart item has been achieved through my views but what i want is that about how can I do this in Admin.

class Product(models.Model):
    product_name=models.CharField(max_length=32)
    price=models.IntegerField()

class Cart(models.Model):
    cust_id=models.ForeignKey(User, on_delete=models.CASCADE)
    count=models.IntegerField(default=0)
    total=models.IntegerField(default=0)

class Cart_Item(models.Model):
    item=models.ForeignKey(Product, blank=True, null=True, on_delete=models.CASCADE)
    quantity=models.IntegerField()
    cart=models.ForeignKey(Cart, on_delete=models.CASCADE)

What I want to achieve in Admin is that that if I add or remove a Cart_Item object in Admin, it should update the corresponding values of count and total in Cart accordingly for that particular user

Upvotes: 1

Views: 261

Answers (1)

Rayyan
Rayyan

Reputation: 302

I would consider count and total to be model methods of Cart, like this:

Solution 1


from django.db.models import Sum

class Product(models.Model):
    product_name=models.CharField(max_length=32)
    price=models.IntegerField()

class Cart(models.Model):
    cust_id=models.ForeignKey(User, on_delete=models.CASCADE)
    # Model Property
    @property
    def count(self):
        return Cart_Item.objects.filter(cart=self).count()
    @property
    def total(self):
        return Cart_Item.objects.filter(cart=self).item.aggregate(Sum('price'))
class Cart_Item(models.Model):
    item=models.ForeignKey(Product, blank=True, null=True, on_delete=models.CASCADE)
    quantity=models.IntegerField()
    cart=models.ForeignKey(Cart, on_delete=models.CASCADE)

You can then access the count and total just like you would access any other field, like this:

cart = Cart(cust_id=user)
items_in_cart = cart.items
total_balance = cart.amount

Solution 2

We can also use the related_name attribute of the model to access the children or "access the model backward":


from django.db.models import Sum

class Product(models.Model):
    product_name=models.CharField(max_length=32)
    price=models.IntegerField()

class Cart(models.Model):
    cust_id=models.ForeignKey(User, on_delete=models.CASCADE)
    # Model Property
    @property
    def count(self):
        return self.cart_items.count()
    @property
    def total(self):
        return self.cart_items.item.aggregate(Sum('price'))
class Cart_Item(models.Model):
    item=models.ForeignKey(Product, blank=True, null=True, on_delete=models.CASCADE)
    quantity=models.IntegerField()
    cart=models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='cart_items')

Why Model Methods?

We need model methods because count and total are being generated dynamically.
If you really would like the model methods to be fields of Cart, you can try this solution.

Please comment if this doesn't work, I'm new to Django.

Upvotes: 2

Related Questions