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件;更新数量的逻辑也写反了,会在原有数量上累加而非替换为传入值
修复步骤
1. 解决核心报错:修正SESSION_COOKIE_AGE配置
打开项目的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
相关产品推荐
相关产品推荐

