Reputation: 107
I have cart model and product model this code work fine to add each product one time into cart ,but I wanna be able to add quantity of a product and update the total after added but I'm not sure where I should add the quantity field any ideas ? My cart model :-
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() == 1:
new_obj = False
cart_obj = qs.first()
else:
cart_obj = Cart.objects.new()
new_obj = True
request.session['cart_id'] = cart_obj.id
return cart_obj, new_obj
def new(self):
return self.model.objects.create()
class Cart(models.Model):
products = models.ManyToManyField(Product, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = CartManager()
def __str__(self):
return str(self.id)
cart views.py file:-
def cart_home(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
context = {
'cart': cart_obj,
}
return render(request, "carts/home.html", context)
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id is not None:
try:
item = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("show message to user, product doesn't exist")
return redirect("carts:cart")
cart_obj, new_obj = Cart.objects.new_or_get(request)
if item in cart_obj.products.all():
cart_obj.products.remove(item)
else:
cart_obj.products.add(item)
return redirect("carts:cart")
I update the subtotal of the cart using m2m_changed signal and then using pre_save signal to add a fixed shipping cost and update total
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
products = instance.products.all()
total = 0
for x in products:
total += x.price
if instance.subtotal != total:
instance.subtotal = total
instance.save()
m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through)
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = instance.subtotal + 50 #shiping cost
else:
instance.total = 0.00
pre_save.connect(pre_save_cart_receiver, sender=Cart)
What I want is adding quantity and update it using a signal like this but I don't know where should I add this quantity field , it should be for every product in the cart. example:-
Cart 1 contains 2 products
product 1 (quantity 2) price of the unit is 50 , total = 50
product 2 (quantity 3) price of the unit is 100 , total = 200
cart total now is 250
I should take the quantity from the user and then multiple it with the unit price then
update the total of the cart
Please any help on how to do that
Upvotes: 1
Views: 5024
Reputation: 107
Ok I figured out a solution for my problem ,
maybe it will help someone in the future
I created a new model called CartItem that has item , item_cart, quantity ,
item_cart is to make sure that the CartItem related to the session cart.
and then in cart model updated the products field to be like this:
products = models.ManyToManyField(CartItem, blank=True)
in the cart_add view I get the product_id and the quantity from a form in the template that has 2 inputs fields one for quantity and a hidden one for the product id:
product_id = request.POST.get('product_id')
quantity = request.POST.get('quantity_field')
then when clicked add to cart I create a new CartItem for this session cart like this:
cart_obj, new_obj = Cart.objects.new_or_get(request)
product = Product.objects.get(id=product_id)
item = CartItem.objects.create(item=product,item_cart=cart_obj, quantity=quantity)
then finally added the item to the cart like this:
cart_obj.products.add(item)
I hope that will help any one :)
Upvotes: 4