我正在尝试为在线商店开发网站,用户可以在其中将产品添加到购物车中。当用户添加或删除产品时,我不知道为什么总价不正确。我是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"
答案 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()