Django开发电商购物车功能触发MultipleObjectsReturned错误如何解决
问题修复方案
错误根因
get_or_create方法参数使用错误:Item.objects.get_or_create(Item)没有传递任何查询过滤条件,等同于查询所有Item对象,当数据库中存在多条Item记录时就会抛出MultipleObjectsReturned异常。- 视图逻辑存在多处与模型定义不匹配的问题:Order模型不存在
item、quantity字段,错误将OrderItem的属性写在了Order上。 OrderItem.objects.get_or_create(active=True)同样没有关联对应商品,也会触发多返回值报错,且原OrderItem模型根本没有定义active字段。- 模型定义缩进错误:Order类错误定义为OrderItem的内部类,二者应为同级模型。
修复步骤
第一步:修正模型定义
调整models.py的结构和必要字段:
from django.db import models from django.contrib.auth.models import User from django.db.models import CASCADE # 原有Item模型示例,可保留你原有字段 class Item(models.Model): name = models.CharField(max_length=200) price = models.DecimalField(max_digits=11, decimal_places=2) # slug为可选字段,非必须添加 class OrderItem(models.Model): order_item = models.ForeignKey(Item, on_delete=CASCADE, null=True) quantity = models.IntegerField(default=1) # 新增用户、下单状态字段,区分不同用户的未结算订单项 user = models.ForeignKey(User, on_delete=CASCADE, null=True) ordered = models.BooleanField(default=False) # 调整缩进,改为和OrderItem同级的类 class Order(models.Model): order_user = models.ForeignKey(User, on_delete=CASCADE) order_items = models.ManyToManyField(OrderItem) ordered = models.BooleanField(default=False) total = models.DecimalField(default=0.00, decimal_places=2, max_digits=11)
第二步:配置URL传递商品标识
修改urls.py,给加购接口传递商品ID参数:
path('add-to-cart/<int:item_id>/', add_to_cart, name='add_to_cart')
第三步:修正视图逻辑
重写add_to_cart视图,符合Django ORM的查询规则:
@login_required def add_to_cart(request, item_id, *args, **kwargs): # 先查询指定商品,不存在直接返回404 item = Item.objects.get(id=item_id) # 获取或创建当前用户未下单的对应商品订单项 order_item, created = OrderItem.objects.get_or_create( order_item=item, user=request.user, ordered=False ) # 查询当前用户未结算的购物车订单 order_qs = Order.objects.filter(order_user=request.user, ordered=False) if order_qs.exists(): order = order_qs.first() # 判断商品是否已在购物车内 if order.order_items.filter(order_item__id=item_id).exists(): # 已存在则数量+1 order_item.quantity += 1 order_item.save() else: # 不存在则新增订单项到订单 order.order_items.add(order_item) else: # 无未结算订单则新建订单并加入订单项 order = Order.objects.create(order_user=request.user) order.order_items.add(order_item) messages.success(request, "Cart updated!") return redirect('cart-page')
关于SlugField的疑问
不需要强制创建SlugField,使用商品ID作为查询条件完全可以满足需求。SlugField一般用于优化URL可读性,如果你希望URL展示为/add-to-cart/apple-iphone-14而非/add-to-cart/123可以添加,添加后只需将视图中的查询条件改为Item.objects.get(slug=传入的slug参数)即可。
内容的提问来源于stack exchange,提问作者user16476339
相关产品推荐
相关产品推荐

