Django使用Session实现购物车时如何在模板中显示Variant规格的价格
Django Session购物车规格价格展示故障修复方案
核心调整是将购物车的存储维度从商品(Product)改为商品规格(Variants),每个购物车条目对应一个独立的规格实例,而非笼统的商品实例
1. 首先调整加购表单,增加规格参数接收
修改CartAddForm,新增尺寸、颜色选择字段,用于接收用户选中的规格:
class CartAddForm(forms.Form): quantity = forms.IntegerField(min_value=1) size = forms.ModelChoiceField(queryset=Size.objects.all()) color = forms.ModelChoiceField(queryset=Color.objects.all()) # 实际生产环境可根据当前商品动态过滤可选规格,避免无效提交
2. 重写Cart购物车核心逻辑
调整存储结构以Variant ID为key,同时修改迭代逻辑绑定规格实例:
CART_SESSION_ID = 'cart' class Cart: def __init__(self, request): self.session = request.session cart = self.session.get(CART_SESSION_ID) if not cart: cart = self.session[CART_SESSION_ID] = {} self.cart = cart def __iter__(self): # 拿取所有购物车中的规格ID variant_ids = self.cart.keys() # 关联查询规格及对应商品信息,减少数据库查询次数 variants = Variants.objects.filter(id__in=variant_ids).select_related('product') cart = self.cart.copy() for variant in variants: cart[str(variant.id)]['variant'] = variant cart[str(variant.id)]['product'] = variant.product # 预计算单条规格的购物车小计 cart[str(variant.id)]['subtotal'] = variant.price * cart[str(variant.id)]['quantity'] # 迭代返回每个购物车条目 for item in cart.values(): yield item def add(self, variant, quantity): variant_id = str(variant.id) if variant_id not in self.cart: # 存储当前规格的价格、数量 self.cart[variant_id] = {'quantity': 0, 'price': str(variant.price)} self.cart[variant_id]['quantity'] += quantity self.save() def save(self): self.session.modified = True
3. 修改加购视图逻辑
根据表单提交的规格参数查询对应Variants实例,传给购物车add方法:
# 加入购物车 def cart_add(request, product_id): cart = Cart(request) product = get_object_or_404(Product, id=product_id) form = CartAddForm(request.POST) if form.is_valid(): cd = form.cleaned_data # 匹配用户选中的规格实例 variant = get_object_or_404(Variants, product=product, size_id=cd['size'], color_id=cd['color'] ) cart.add(variant=variant, quantity=cd['quantity']) return redirect('cart:details')
4. 调整模板输出
直接从绑定的variant实例中拿取对应规格的价格即可:
{% for c in cart %} <tr> <td>{{ c.product.name }}</td> <td>颜色:{{ c.variant.color.name }} | 尺寸:{{ c.variant.size.name }}</td> <td>{{ c.variant.price }}</td> <td>小计:{{ c.subtotal }}</td> </tr> {% endfor %}
内容的提问来源于stack exchange,提问作者h_python_1368
相关产品推荐
相关产品推荐

