Django电子商务视图的问题与增加数量增加或减少产品相同的产品Id,但不同的选项Id值



我的问题可能是一些简单的东西,但我一直被困在它。我试图使我的电子商务购物车增加数量上下,同时删除实例时,数量达到零。问题是,当你在另一个具有相同基础Product_idcart_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:UsersdaveDesktoptnaecommercevenvLibsite-packagesdjangodbmodelsquery.py, line 433, in get Python Executable:    C:UsersdaveDesktoptnaecommercevenvScriptspython.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)

url.py

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_itemid的变化,并且在使其向下递增方面取得了一些成功。我只是不能让数字上升,增加更多的实例。

我确信解决方案是我如何在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功能与其他所有正在发生的事情。只有当您尝试添加另一个包含选项的项时,才会出现此错误。一个基本级别的选项就可以了

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()方法

最新更新