Django Ecommerce查看增加或减少具有相同商品ID但不同选项ID值的商品数量的问题

mnemlml8  于 2022-12-27  发布在  Go
关注(0)|答案(1)|浏览(126)

我的问题可能很简单,但我一直在解决这个问题。我试图让我的电子商务购物车增加和减少数量,同时在数量为零时删除示例。问题是,当您向具有相同基本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_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功能中,以及上面正在进行的其他操作。只有当您尝试添加另一个包含选项的项时,才会出现错误。

vcudknz3

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

相关问题