You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django开发购物车报float与str类型不支持+运算错误

问题根因

别在Cart类代码里找float和str相加的问题,报错出在Django session中间件计算cookie过期时间的逻辑:expires_time = time.time() + max_age。这里time.time()返回浮点数时间戳,max_age读取的是settings里的SESSION_COOKIE_AGE配置,你把这个配置项的值写成了字符串类型,两个类型无法相加才触发报错,和你贴的购物车业务代码没有直接关系。

另外你写的Cart类本身有两个逻辑bug,修完配置后如果不改,后续加购、遍历购物车时会出问题:

  • __iter__方法只给购物车字典绑定了product对象,没有用yield返回迭代条目,直接遍历Cart实例拿不到商品数据
  • add方法逻辑不全:默认非更新数量的场景下,商品已存在购物车时不会累加数量,永远只保留第一次添加的1件;更新数量的逻辑也写反了,会在原有数量上累加而非替换为传入值
修复步骤

打开项目的settings.py,找到SESSION_COOKIE_AGE配置,把值改为整数类型,不要加引号:

# 错误示例(字符串类型,就是这个配置触发的报错)
# SESSION_COOKIE_AGE = "1209600"

# 正确配置(整数,单位为秒,Django默认值1209600对应14天有效期)
SESSION_COOKIE_AGE = 1209600

如果你没有手动写过这个配置,检查有没有其他地方给session设置max_age时传了字符串值,比如在视图里手动调用request.session.set_expiry()时传了带引号的数字。

2. 修复Cart类的逻辑漏洞

替换cart.py的代码为修正版本:

from django.conf import settings
from Products.models import Product

class Cart(object):
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)
        if not cart:
            cart = self.session[settings.CART_SESSION_ID] = {}
        self.cart = cart
    
    def __iter__(self):
        # 批量查询商品,避免循环单查造成N+1问题
        product_ids = self.cart.keys()
        products = Product.objects.filter(id__in=product_ids)
        for product in products:
            cart_item = self.cart[str(product.id)]
            cart_item['product'] = product
            # 统一把数量转为整数,避免后续计算出现类型问题
            cart_item['quantity'] = int(cart_item['quantity'])
            yield cart_item
    
    def __len__(self):
        return sum(int(item['quantity']) for item in self.cart.values())
    
    def save(self):
        self.session[settings.CART_SESSION_ID] = self.cart
        self.session.modified = True
    
    def add(self, product_id, quantity=1, update_quantity=False):
        product_id = str(product_id)

        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 0, 'id': product_id}
        
        if update_quantity:
            # 更新数量模式:直接替换为传入的数量值
            self.cart[product_id]['quantity'] = int(quantity)
        else:
            # 普通加购模式:在原有数量上累加
            self.cart[product_id]['quantity'] += int(quantity)

        # 数量小于等于0时直接移除商品
        if self.cart[product_id]['quantity'] <= 0:
            self.remove(product_id)
            
        self.save()
    
    def remove(self, product_id):
        product_id = str(product_id)
        if product_id in self.cart:
            del self.cart[product_id]
            self.save()

3. 优化加购视图逻辑

你现在写的add_to_cart视图不管GET/POST请求都会直接加购,刷新页面会重复提交,建议调整为:

from django.shortcuts import render, redirect, get_object_or_404
from Products.models import Product

def add_to_cart(request, product_id):
    # 先校验商品是否存在,不存在直接返回404
    product = get_object_or_404(Product, id=product_id)
    cart = Cart(request)
    # 从请求参数读取购买数量,默认1
    quantity = int(request.POST.get('quantity', 1))
    cart.add(product_id=product_id, quantity=quantity, update_quantity=False)
    # 加购完成后跳转到购物车页面,避免刷新重复提交
    return redirect('cart_detail') # 替换为你自己项目里购物车页的路由别名
验证方式

修改完SESSION_COOKIE_AGE的类型后,重启Django开发服务器,再访问页面就不会触发类型错误,后续加购、统计购物车商品总数、遍历购物车商品的逻辑都可以正常运行。

内容的提问来源于stack exchange,提问作者Berkant Dirim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:40:05