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
1 Answer
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.
6