Abdelrahman Mamdouh
Abdelrahman Mamdouh

Reputation: 107

how to add quantity of products and update total in cart using django?

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

Answers (1)

Abdelrahman Mamdouh
Abdelrahman Mamdouh

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

Related Questions