Django购物车在添加产品时更新子总数,但是当产品被删除时,小计不会更新

时间:2017-03-09 17:22:07

标签: python ajax django

购物车应用

models.py

from decimal import Decimal
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models.signals import pre_save, post_save


from products.models import Variation
# Create your models here.


class CartItem(models.Model):
    cart = models.ForeignKey("Cart")
    item = models.ForeignKey(Variation)
    quantity = models.PositiveIntegerField(default=1)
    line_item_total = models.DecimalField(max_digits=10, decimal_places=2)

    def __unicode__(self):
        return self.item.title

    def remove(self):
        return self.item.remove_from_cart()


def cart_item_pre_save_receiver(sender, instance, *args, **kwargs):
    qty = instance.quantity
    if qty >= 1:
        price = instance.item.get_price()
        line_item_total = Decimal(qty) * Decimal(price)
        instance.line_item_total = line_item_total

pre_save.connect(cart_item_pre_save_receiver, sender=CartItem)



def cart_item_post_save_receiver(sender, instance, *args, **kwargs):
    instance.cart.update_subtotal()

post_save.connect(cart_item_post_save_receiver, sender=CartItem)




class Cart(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    items = models.ManyToManyField(Variation, through=CartItem)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    subtotal = models.DecimalField(max_digits=50, decimal_places=2)

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

    def update_subtotal(self):
        print "updating..."
        subtotal = 0
        items = self.cartitem_set.all()
        for item in items:
            subtotal += item.line_item_total
        self.subtotal = subtotal
        self.save()

views.py

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, Http404, JsonResponse
from django.shortcuts import render, get_object_or_404
from django.views.generic.base import View
from django.views.generic.detail import SingleObjectMixin


# Create your views here.

from products.models import Variation
from carts.models import Cart, CartItem

class CartView(SingleObjectMixin, View):
    model = Cart
    template_name = "carts/view.html"

    def get_object(self, *args, **kwargs):
        self.request.session.set_expiry(0) #5 minutes
        cart_id = self.request.session.get("cart_id")
        if cart_id == None:
            cart = Cart()
            cart.save()
            cart_id = cart.id
            self.request.session["cart_id"] = cart_id
        cart = Cart.objects.get(id=cart_id)
        if self.request.user.is_authenticated():
            cart.user = self.request.user
            cart.save()
        return cart

    def get(self, request, *args, **kwargs):
        cart = self.get_object()
        item_id = request.GET.get("item")
        delete_item = request.GET.get("delete", False)
        item_added = False
        if item_id:
            item_instance = get_object_or_404(Variation, id=item_id)
            qty = request.GET.get("qty", 1)
            try:
                if int(qty) < 1:
                    delete_item = True
            except:
                raise Http404
            cart_item, created = CartItem.objects.get_or_create(cart=cart, item=item_instance)
            if created:
                item_added = True
            if delete_item:
                cart_item.delete()
            else:
                cart_item.quantity = qty
                cart_item.save()
            if not request.is_ajax():
                return HttpResponseRedirect(reverse("cart"))
                #return cart_item.cart.get_absolute_url()

        if request.is_ajax():
            try:
                total = cart_item.line_item_total
            except:
                total = None
            try:
                subtotal = cart_item.cart.subtotal
            except:
                subtotal = None
            data = {
                    "deleted": delete_item, 
                    "item_added": item_added,
                    "line_total": total,
                    "subtotal": subtotal,
                    }

            return JsonResponse(data) 


        context = {
            "object": self.get_object()
        }
        template = self.template_name
        return render(request, template, context)

view.html

{% extends "base.html" %}


<script>
{% block jquery %}
$(".item-qty").change(function(){
    // $(this).next(".btn-update").fadeIn();
    // event.preventDefault();
    // .prev(h1)
    var item = $(this).prev("input[type='hidden']").val();
    var qty = $(this).val()
    var data = {
        item: item,
        qty: qty
    }
    console.log(data);
    $.ajax({
        type: "GET", // "POST"
        url: "{% url 'cart' %}",
        data: data,
        success: function(data) {
            $("#jquery-message").text("Added " + data.item_added + " Deleted " + data.deleted)
            if (data.deleted){
                $("#item-"+item).fadeOut();
            } else {
                $("#item-line-total-"+item).text(data.line_total);
                $("#subtotal").text(data.subtotal);
            }
        }, 
        error: function(response, error) {
            // console.log(response)
            // console.log(error)
            $("#add-form").submit()
        }
    })
});
{% endblock %}
</script>

{% block content %}


<table class='table'> 

{% for item in object.cartitem_set.all %}

<tr id='item-{{ item.item.id }}'>

<td>{{ item.item.get_title }}</td>


<td><form action="." method="GET" ><input type='hidden' name='item' value='{{ item.item.id }}' /><input type='number' class='item-qty' name='qty' value='{{ item.quantity }}' /><input type='submit' class='btn-update btn btn-link' value='Update item' style='display:none;'/></form></td>
<td id='item-line-total-{{ item.item.id }}'>{{ item.line_item_total }}</td>
<td class='text-right' ><a href='{{ item.remove }}'>X</a>



</td>


</tr>

{% endfor %}


<tr>
<td id='subtotal' colspan='4' class='text-right'>Subtotal: {{ object.subtotal }}</td>

</tr>

</table>
{% endblock %}

当我更新数量时,购物车小计也在更新,但仅在项目删除时才更新。

对于购物车的自动更新,我使用的是Ajax

更新:

包含{{item.remove}}在内部但仍然没有更改小计并且也没有错误

我还注意到,在我的管理员手动删除购物车中的商品时,小计也没有改变

1 个答案:

答案 0 :(得分:0)

在看了我的模型后,我发现有些东西丢失了,这是删除后的内容,在添加了一行后,小计开始获得更新项目的删除

from decimal import Decimal
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models.signals import pre_save, post_save, post_delete


from products.models import Variation
# Create your models here.


class CartItem(models.Model):
    cart = models.ForeignKey("Cart")
    item = models.ForeignKey(Variation)
    quantity = models.PositiveIntegerField(default=1)
    line_item_total = models.DecimalField(max_digits=10, decimal_places=2)

    def __unicode__(self):
        return self.item.title

    def remove(self):
        return self.item.remove_from_cart()


def cart_item_pre_save_receiver(sender, instance, *args, **kwargs):
    qty = instance.quantity
    if qty >= 1:
        price = instance.item.get_price()
        line_item_total = Decimal(qty) * Decimal(price)
        instance.line_item_total = line_item_total

pre_save.connect(cart_item_pre_save_receiver, sender=CartItem)



def cart_item_post_save_receiver(sender, instance, *args, **kwargs):
    instance.cart.update_subtotal()

post_save.connect(cart_item_post_save_receiver, sender=CartItem)

post_delete.connect(cart_item_post_save_receiver, sender=CartItem)



class Cart(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    items = models.ManyToManyField(Variation, through=CartItem)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    subtotal = models.DecimalField(max_digits=50, decimal_places=2)

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

    def update_subtotal(self):
        print "updating..."
        subtotal = 0
        items = self.cartitem_set.all()
        for item in items:
            subtotal += item.line_item_total
        self.subtotal = subtotal
        self.save()