如何实现未授权访客添加商品至购物车?解决Django 404错误
解决访客添加商品到购物车时的404错误
问题根源
出现No Session matches the given query的404错误,核心原因有三点:
- 调用
request.session.create()后,Django仅生成session_key,但未立刻将Session对象写入数据库,此时用get_object_or_404(Session, ...)会找不到对应记录 CartPage视图直接用get_object_or_404获取购物车,访客可能还未创建购物车,触发404Cart模型中同时存在items多对多关联和CartItem的外键关联,造成逻辑冗余与冲突
分步修复
1. 修复shop/views.py的add_to_cart方法
调整Session获取逻辑,确保数据库中存在对应Session记录,同时优化商品获取的安全性:
def add_to_cart(self, request, wine_slug): session_key = request.session.session_key if not session_key: request.session.create() session_key = request.session.session_key # 确保数据库中存在该Session记录 session, _ = Session.objects.get_or_create(session_key=session_key) # 用get_object_or_404处理商品不存在的场景 product = get_object_or_404(Wine, slug=wine_slug) cart, created = Cart.objects.get_or_create(session=session) cart_item, item_created = CartItem.objects.get_or_create(cart_items=cart, product=product) cart_item.quantity += 1 cart_item.save() return redirect('cart')
2. 修复orders/views.py的CartPage视图
允许访客自动创建购物车,避免直接使用get_object_or_404导致的404:
class CartPage(View): template = 'orders/cart.html' def get(self, request): session_key = request.session.session_key session = Session.objects.filter(session_key=session_key).first() if session_key else None # 获取或创建当前会话对应的购物车 cart, created = Cart.objects.get_or_create(session=session) items = CartItem.objects.filter(cart_items=cart) def item_total(): summ = 0.0 for each in items: summ += each.product.price * each.quantity return summ context = { 'cart': cart, 'item': items, 'item_total': item_total() } return render(request, self.template, context)
3. 清理orders/models.py的冗余关联
移除Cart模型中的items字段,因为CartItem已通过外键关联到Cart,无需重复关联:
class Cart(models.Model): session = models.ForeignKey(Session, null=True, blank=True, on_delete=models.CASCADE) date_generation = models.DateField(auto_now=True) def __str__(self): return str(self.date_generation) class CartItem(models.Model): cart_items = models.ForeignKey(Cart, on_delete=models.CASCADE) product = models.ForeignKey(Wine, on_delete=models.PROTECT) quantity = models.IntegerField(default=0) def __str__(self): return str(self.pk)
额外说明
- 访客的购物车会通过Session关联,Session过期后,购物车数据会保留在数据库中,可通过定时任务清理过期Session对应的Cart
- 若需实现用户登录后合并访客购物车,可在用户登录信号中处理Cart的关联转移
内容的提问来源于stack exchange,提问作者Roma
相关产品推荐
相关产品推荐

