我的问题可能很简单,但我一直在解决这个问题。我试图让我的电子商务购物车增加和减少数量,同时在数量为零时删除示例。问题是,当您向具有相同基本Product_id
的另一个cart_item
示例中的产品添加选项时,它会引发错误。
我知道它将同一个product_id
的不同示例拉入同一个get请求,但我不确定如何解决它。
MultipleObjectsReturned at /cart/add_cart/2/ get() returned more than one CartItem -- it returned 2! Request Method: GET Request URL: http://127.0.0.1:8000/cart/add_cart/2/ Django Version: 3.1 Exception Type: MultipleObjectsReturned Exception Value: get() returned more than one CartItem -- it returned 2! Exception Location: C:\Users\dave\Desktop\tnaecommerce\venv\Lib\site-packages\django\db\models\query.py, line 433, in get Python Executable: C:\Users\dave\Desktop\tnaecommerce\venv\Scripts\python.exe Python Version: 3.11.0 Python Path: ['C:\\Users\\dave\\Desktop\\tnaecommerce\\ecomwebsite\\tnaecom', 'C:\\Python311\\python311.zip', 'C:\\Python311\\DLLs', 'C:\\Python311\\Lib', 'C:\\Python311', 'C:\\Users\\dave\\Desktop\\tnaecommerce\\venv', 'C:\\Users\\dave\\Desktop\\tnaecommerce\\venv\\Lib\\site-packages'] Server time: Mon, 19 Dec 2022 16:19:11 +0000
views.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import Cart, CartItem
from store.models import Product, ProductOption
from django.core.exceptions import ObjectDoesNotExist
from decimal import Decimal
from django.http import HttpResponse
from decimal import Decimal
from django.views import View
from django.views.generic.edit import DeleteView
def _cart_id(request):
cart = request.session.session_key
if not cart:
cart = request.session.create()
return cart
def add_cart(request, product_id, quantity=1):
product = Product.objects.get(id = product_id) # get the product
product_options= request.POST.getlist('option')#gets selected product options
#
try:
cart = Cart.objects.get(cart_id = _cart_id(request) ) # gets cart using private function above
except Cart.DoesNotExist:# creates a new cart instance if it doesnt exist
Cart.objects.create(
cart_id = _cart_id(request)
)
cart.save()#saves new cart if needed to be created
try:
cart_item = CartItem.objects.get(product = product, cart = cart)
# if the product has multiple options, check if any of the options in the cart item matches the selected options
if len(product_options) > 0:
match = False
for option in cart_item.options.all():
if option in product_options:
match = True
# adding to attempt to fix quantity increment up +1
quantity += quantity
cart_item.save()
# if none of the cart item options matches the selected options, add new cart item with selected options
if not match:
cart_item = CartItem.objects.create(
product = product,
cart = cart,
quantity = quantity,
)
if len(product_options) > 0:
for item in product_options:
cart_item.options.add(item)
cart_item.save()
else:
cart_item.quantity += quantity # adds the specified quantity of a single instance of product cart item
cart_item.save()
except CartItem.DoesNotExist:
cart_item = CartItem.objects.create(
product = product,
cart = cart,
quantity = quantity
)
if len(product_options) > 0:
for item in product_options:
cart_item.options.add(item)
cart_item.save()
return redirect("cart")
def remove_cart(request, product_id):
cart = Cart.objects.get(cart_id= _cart_id(request))
product = get_object_or_404(Product, id = product_id)
cart_item = CartItem.objects.get(product=product, cart=cart)
if cart_item.quantity > 1:
cart_item.quantity -= 1
cart_item.save()
else:
cart_item.delete()
return redirect('cart')
def remove_cart_item(request, id):
cart_item = CartItem.objects.get(id=id) # get the cart item
# get the cart
try:
cart = Cart.objects.get(cart_id = _cart_id(request) ) # gets cart using private function above
except Cart.DoesNotExist:# creates a new cart instance if it doesnt exist
Cart.objects.create(
cart_id = _cart_id(request)
)
cart.save()#saves new cart if needed to be created
if cart_item.quantity > 1:
cart_item.quantity -= 1
cart_item.save()
else:
cart_item.delete() # save the cart item if there are still items left in the cart
return redirect("cart")
def cart(request, total = 0,total_savings=0, quantity=0, cart_items= None):
try:
cart = Cart.objects.get(cart_id = _cart_id(request))
cart_items = CartItem.objects.filter(cart=cart, is_active=True)
for cart_item in cart_items:
total += cart_item.subtotal
total_savings += cart_item.savings
quantity = cart_item.quantity
except ObjectDoesNotExist:
pass
context = {
'total': total,
'quantity': quantity,
'total_savings': total_savings,
'cart_items': cart_items,
}
return render (request, 'store/cart.html', context)
一米四分一秒
from django.urls import path
from . import views
'''
/cart/ starting url from root url
'''
urlpatterns = [
path('', views.cart, name='cart'),
path('add_cart/<int:product_id>/', views.add_cart, name = 'add_cart'),
path('remove_cart/<int:product_id>/', views.remove_cart, name = 'remove_cart'),
#path('remove_cart_item/<int:product_id>/', views.remove_cart_item, name = 'remove_cart_item'),
path('remove_cart_item/<int:id>/', views.remove_cart_item, name = 'remove_cart_item')
]
models.py
from django.db import models
from store.models import *
from decimal import Decimal
# Create your models here.
class CouponCode(models.Model):
"""Model definition for CouponCode."""
name = models.CharField("Coupon Code Name", max_length=50)
code = models.CharField("Verbatim Coupon Code", max_length=50)
discount = models.DecimalField("Discount as decimal of 100", max_digits=3, decimal_places=2, help_text="For a 20 percent discount enter .80")
usagecount = models.IntegerField(default=0)
products = models.ManyToManyField(Product)
is_active = models.BooleanField(default=False)
# TODO: Define fields here
class Meta:
"""Meta definition for CouponCode."""
verbose_name = 'CouponCode'
verbose_name_plural = 'CouponCodes'
def __str__(self):
"""Unicode representation of CouponCode."""
return f"Coupon: {self.name}, Code: {self.discount}, Active: {self.is_active}"
class Cart(models.Model):
"""Model definition for Cart."""
cart_id = models.CharField(max_length= 250, blank = True)
date_added = models.DateField("Date Added", auto_now_add=True)
# TODO: Define fields here
class Meta:
"""Meta definition for Cart."""
verbose_name = 'Cart'
verbose_name_plural = 'Carts'
def __str__(self):
"""Unicode representation of Cart."""
return self.cart_id
class CartItem(models.Model):
"""Still need to write loop function adding product option cost to
base product price."""
product = models.ForeignKey(Product, on_delete = models.CASCADE)
options = models.ManyToManyField( ProductOption, blank=True)
cart = models.ForeignKey(Cart, on_delete = models.CASCADE, null=True)
quantity = models.IntegerField(default=1)
is_active = models.BooleanField(default = True)
date_added = models.DateTimeField("Date/Time added", auto_now=False, auto_now_add=True)
# TODO: Define fields here
@property #
def subtotal(self):
option_subtotal=0
for item in self.options.all():
option_subtotal += item.price
original_price = self.product.product_price + option_subtotal#- self.couponcode
quantity = self.quantity
price = original_price
quantity = self.quantity
if quantity >= 10:
price = round(price * Decimal(.80),2)
elif quantity >= 8:
price = round(price * Decimal(.85),2)
elif quantity >= 6:
price = round(price * Decimal(.90),2)
elif quantity >= 4:
price = round(price * Decimal(.93),2)
elif quantity >= 2:
price = round(price * Decimal(.95),2)
else:
price = round(price, 2)
# rounding price to 2 decimal places
price = price
subtotal = price * quantity
return subtotal
@property #
def savings(self):
option_subtotal=0
quantity = self.quantity
for item in self.options.all():
option_subtotal += item.price
original_price = self.product.product_price + option_subtotal
original_price *= quantity
price = original_price
'''Coupon code discount '''
quantity = self.quantity
if quantity >=10:
price = round(price * Decimal(.80),2)
elif quantity >=8:
price = round(price * Decimal(.85),2)
elif quantity >=6:
price = round(price * Decimal(.90),2)
elif quantity >=4:
price = round(price * Decimal(.93),2)
elif quantity >=2:
price = round(price * Decimal(.95),2)
else:
price = round(price,2)
# rounding price to 2 decimal places
savings = original_price - price
return savings
@property
def orig_price(self):
option_subtotal=0
quantity = self.quantity
for item in self.options.all():
option_subtotal += item.price
original_price = self.product.product_price + option_subtotal
original_price = original_price * quantity
return original_price
class Meta:
""" Meta definition for CartItem """
verbose_name = 'CartItem'
verbose_name_plural = 'CartItems'
def __str__(self):
""" Unicode representation of CartItem """
return f"CartItem ID: {self.id}, Product: {self.product}, Quantity: {self.quantity},Cart: {self.cart.id},"
为了解决这个问题,我尝试了多种直接拉取cart_item
id 的方法,并成功地让它向下递增,但我无法让数字向上增加并添加更多示例。
我确信解决方案是我如何在remove_cart_item
中向下增加数量值的一些变化:
def remove_cart_item(request, id):
cart_item = CartItem.objects.get(id=id) # get the cart item
# get the cart
try:
cart = Cart.objects.get(cart_id = _cart_id(request) ) # gets cart using private function above
except Cart.DoesNotExist:# creates a new cart instance if it doesnt exist
Cart.objects.create(
cart_id = _cart_id(request)
)
cart.save()#saves new cart if needed to be created
if cart_item.quantity > 1:
cart_item.quantity -= 1
cart_item.save()
else:
cart_item.delete() # save the cart item if there are still items left in the cart
return redirect("cart")
我只是不确定如何将其实现到add_cart
功能中,以及上面正在进行的其他操作。只有当您尝试添加另一个包含选项的项时,才会出现错误。
1条答案
按热度按时间vcudknz31#
在
add-cart
函数中获取cart-items
时使用filter()而不是get()。cart_item = CartItem.objects.filter(product = product, cart = cart)
。get()返回filter返回示例的模型对象。您有一个购物车,其中有许多购物车项目。因此,为了获取它,您必须使用filter()。因此,您面临错误,因为当get()方法仅返回一个对象时,收到更多数据的购物车项目。错误本身表明
MultipleObjectsReturned at /cart/add_cart/2/ get() returned more than one CartItem -- it returned 2!
。因此,使用filter()方法