Добавление количества товара и его обновление в корзине с помощью django

Я прохожу видеоурок по электронной коммерции на django, в котором я могу добавить товар в корзину с помощью Ajax, но не могу обновить количество товара в корзине. Я просмотрел много видеоуроков, а также много вопросов на stack overflow и много блогов, но не смог найти решение. пожалуйста, помогите мне

Product/models.py

class Product(models.Model):
    title = models.CharField(max_length=120)
    price = models.DecimalField(decimal_places=2, max_digits=20)
    quantity = models.IntegerField(default=1)

cart/models.py

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()
            if request.user.is_authenticated and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
        else:
            cart_obj = Cart.objects.new(user=request.user)
            new_obj = True
            request.session['cart_id'] = cart_obj.id
        return cart_obj, new_obj

    def new(self, user=None):
        user_obj = None
        if user is not None:
            if user.is_authenticated:
                user_obj=user
        return self.model.objects.create(user=user_obj)

class Cart(models.Model):
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
    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)
    updated = models.DateTimeField(auto_now=True)
    timestamp = models.DateTimeField(auto_now_add=True)

    objects = CartManager()

    def __str__(self):
        return str(self.id)

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 = Decimal(instance.subtotal) * Decimal(1.08) #8 percent tax
    else:
        instance.total = 0.00
pre_save.connect(pre_save_cart_receiver, sender=Cart )

cart/views.py

def cart_detail_api_view(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    products = [{
                "id": x.id,
                "url": x.get_absolute_url(),
                "name": x.name,
                "price": x.price,
                }
                for x in cart_obj.products.all()]
    cart_data = {"products": products, "subtotal":cart_obj.subtotal, "total":cart_obj.total}
    return JsonResponse(cart_data)

def cart_home(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    return render(request, "carts/cart.html", {"cart": cart_obj})


def cart_update(request):
    product_id = request.POST.get('product_id')
    if product_id is not None:
        try:
            product_obj = Product.objects.get(id=product_id)
        except Product.DoesNotExist:
            print("Show message to user, product is gone?")
            return redirect("cart:home")
        cart_obj, new_obj = Cart.objects.new_or_get(request)
        if product_obj in cart_obj.products.all():
            cart_obj.products.remove(product_obj)
            added = False
        else:
            cart_obj.products.add(product_obj)  # cart_obj.products.add(product_id)
            added = True
        request.session['cart_items'] = cart_obj.products.count()
        # return redirect(product_obj.get_absolute_url())
        if request.is_ajax(): # Asynchronous javascript and xml / Json
            print("ajax request")
            json_data = {
                "added": added,
                "removed": not added,
                "cartItemCount": cart_obj.products.count(),
            }
            return JsonResponse(json_data)
            # return JsonResponse({"message": "error 400"}, status=400)
    return redirect("cart:home")

product.html

<form class="d-flex form-product-ajax" method="POST" action="{% url 'cart:update' %}"
      data-endpoint="{% url 'cart:update' %}">
    {% csrf_token %}
    <input type="hidden" name="product_id" value="{{ product.id }}">
    <span class="submit-span">
        {% if product in cart.products.all %}
        <h6 class="text-light  mb10">Quantity</h6>
            <input type="number" name="quantity" value="1" min="1" max="9999">
            In Cart <button class="btn btn-link" type="submit">Remove?</button>
        {% else %}
            <button class="btn btn-success" type="submit">Add to Cart</button>
        {% endif %}
        </span>
</form>

ajax.js

productForm.submit(function(event){
      event.preventDefault();
      var thisForm = $(this)
      var actionEndpoint = thisForm.attr("data-endpoint")
      var httpMethod = thisForm.attr("method");
      var formData = thisForm.serialize();

      $.ajax({
        url: actionEndpoint,
        method: httpMethod,
        data: formData,
        success: function(data){
          var submitSpan = thisForm.find(".submit-span")
          if (data.added){
            submitSpan.html("" +
                "            <input type=\"number\" name=\"quantity\" value=\"1\" min=\"1\" max=\"9999\">\n" + <a class='btn btn-link'>In cart</a> <button type='submit' class='btn btn-link'>Remove?</button></div>")
          } else {
            submitSpan.html("<button type='submit'  class='btn btn-success'>Add to cart</button>")
           }
          var navbarCount = $(".navbar-cart-count")
          navbarCount.text(data.cartItemCount)
          var currentPath = window.location.href

          if (currentPath.indexOf("cart") != -1) {
            refreshCart()
          }
        },
        error: function(errorData){
          $.alert({
            title: "Oops!",
            content: "An error occurred",
            theme: "modern",
          })
        }
      })
  })
Вернуться на верх