有办法解决这个问题吗?

时间:2020-03-29 08:17:43

标签: python django

我正在尝试为在线商店开发网站,用户可以在其中将产品添加到购物车中。当用户添加或删除产品时,我不知道为什么总价不正确。我是Django的初学者。我该如何解决?

我的views.py:

from django.shortcuts import render, redirect, HttpResponseRedirect, Http404
from products.models import Product
from .models import Cart
from django.contrib import messages
from django.urls import reverse
from django.utils.safestring import mark_safe


def cart(request):
    cart = Cart.objects.all()[0]
    context = {"cart":cart}
    template = 'shopping_cart/cart.html'
    return render(request, template, context)


def add_to_cart(request, slug):
    cart = Cart.objects.all()[0]
    try:
        product = Product.objects.get(slug=slug)
    except Product.DoesNotExist:
        raise Http404
    except:
        pass 
    if not product in cart.products.all():
        cart.products.add(product)
        messages.success(request, mark_safe("Product added to cart. Go to <a href='cart/'>cart</a>"))
        return redirect('myshop-home')
    else:
        cart.products.remove(product)
        messages.success(request, mark_safe("Product removed from cart"))


    new_total = 0.00
    for item in cart.products.all():
        new_total += float(item.price)

    cart.total = new_total
    cart.save()

   return HttpResponseRedirect(reverse('cart'))

我的模型。py:

from django.db import models
from products.models import Product


class Cart(models.Model):
    products = models.ManyToManyField(Product, null=True, blank=True)
    total = models.DecimalField(max_digits=100, decimal_places=2, default = 0.00)

    def __unicode__(self):
        return "Cart"

2 个答案:

答案 0 :(得分:1)

您应将购物车与会话相关联。这样,无论登录状态如何,任何用户都将始终拥有自己的购物车。为了方便起见,您可以使用自定义中间件:

# middleware.py
def cart_from_request(self, request):       
    try:
        cart_pk = request.session.get('_cart_pk')
        return Cart.objects.get(pk=cart_pk)
    except Cart.DoesNotExist:
        cart = Cart.objects.create()
        request.session['_cart_pk'] = cart.pk
        return cart

class CartMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.cart = cart_from_request(request)
        return self.get_response(request)

并将其添加到您的中间件堆栈中:

# settings.py

MIDDLEWARE = [
    # ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    # ...
    'dotted.path.to.middleware.CartMiddleware',
    # ...
]

在任何视图中,您现在都可以直接访问request.cart。 话虽如此,让购物车维持自己的总数是不必要的冗余。为什么不将其设置为属性:

from django.db.models.aggregates import Sum

class Cart(...):
    # ...

    @property
    def total(self):
        return self.products.aggregate(total=Sum('price'))['total'] or 0

答案 1 :(得分:1)

您没有包括Product的模型,但我想您那里也有一个DecimalField。

我认为您唯一的问题可能是您要转换为浮动。在这里使用DecimalField是正确的,其原因是您要避免使用float,因为float并不像您想象的那么精确。

from decimal import Decimal
# ...
    new_total = Decimal()
    for item in cart.products.all():
        new_total += item.price
cart.total = new_total
cart.save()

或者,甚至更好的是,使用内置的sum()和迭代器(无需在此处导入Decimal):

cart.total = sum(item.price for item in cart.products.all())
cart.save()

或者,通过不从数据库中加载所有对象来加快速度:

cart.total = sum(cart.products.values_list('price', flat=True))
cart.save()