Django中CartItem对象无法JSON序列化的问题排查求助
问题:Django中CartItem对象无法存入Session导致JSON序列化错误
我编写了一个Django视图类AddCart,用于将CartItem对象列表存储到session中,但调用该视图的POST方法时触发了JSON序列化错误。
相关代码
AddCart视图类
class AddCart(View): def post(self, *args, **kwargs): prod_id = self.request.POST.get('prod-id') product = Product.objects.get(pk=prod_id) quantity = int(self.request.POST.get('quantity')) cart = self.request.session.get('CART_ID') if cart is None: cart = Cart(self.request) cartItem = CartItem(product_id=prod_id, name=product.name, quantity=quantity, image=product.image, totalprice=float(product.price) * quantity, unitprice=product.price) cart.update(cartItem) print("Cart updated in View") # del self.request.session[settings.CART_ID] return JsonResponse({'status': 'Added to cart'})
Cart类
class Cart(object): def __init__(self, request): self.session = request.session cart_id = settings.CART_ID cart = request.session.get(cart_id) self.cart = cart if cart else [] def update(self, cartItem): cartList = self.cart print("cart list",cartList, "cartItem:",cartItem) found = False totalquantity = 0 for cart in cartList: if cart.product_id == cartItem.product_id: found = True totalquantity = cart.quantity + cartItem.quantity cartList.remove(cart) if not found: cartList.append(cartItem) else: newItem = CartItem(product_id=cartItem.product_id,name=cartItem.name,image=cartItem.image,quantity=totalquantity,unitprice=cartItem.unitprice,totalprice=totalquantity*cartItem.unitprice) cartList.append(newItem) self.cart = cartList self.session[settings.CART_ID] = cartList def __len__(self): return len(self.cart)
CartItem类
class CartItem(object): def __init__(self, product_id, name, image, quantity, unitprice, totalprice): self.product_id = product_id self.name = name self.image = image self.quantity = quantity self.unitprice = unitprice self.totalprice = totalprice def __str__(self): return f"{self.product_id}-{self.name}-{self.image}-{self.quantity}-{self.unitprice}-{self.totalprice}"
错误信息
Internal Server Error: /add-cart/ ... File "C:\Users\enarban\AppData\Local\Programs\Python\Python312\Lib\json\encoder.py", line 258, in iterencode return _iterencode(o, 0) ^^^^^^^^^^^^^^^^^ File "C:\Users\enarban\AppData\Local\Programs\Python\Python312\Lib\json\encoder.py", line 180, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type CartItem is not JSON serializable [11/Aug/2024 15:32:44] "POST /add-cart/ HTTP/1.1" 500 122549
问题原因
Django的Session默认使用JSON格式序列化存储数据,而自定义的CartItem是普通Python类实例,Python标准JSON编码器无法识别这种自定义对象,因此在执行self.session[settings.CART_ID] = cartList时,尝试序列化CartItem对象就会抛出错误。
解决方法
方法1:将CartItem转换为字典存储
这是最直接的解决方案,通过把CartItem对象转换成字典存入Session,取出时再将字典还原为CartItem对象。
- 给
CartItem类添加转字典的方法:
class CartItem(object): # 原有代码不变 def to_dict(self): return { 'product_id': self.product_id, 'name': self.name, 'image': self.image, 'quantity': self.quantity, 'unitprice': self.unitprice, 'totalprice': self.totalprice }
- 修改
Cart类的__init__方法,从Session取出字典时还原为CartItem对象:
class Cart(object): def __init__(self, request): self.session = request.session cart_id = settings.CART_ID cart_data = request.session.get(cart_id) if cart_data: # 将字典列表转换为CartItem对象列表 self.cart = [CartItem(**item) for item in cart_data] else: self.cart = [] # 其他方法不变
- 修改
Cart.update方法,存入Session时使用字典:
def update(self, cartItem): cartList = self.cart print("cart list",cartList, "cartItem:",cartItem) found = False totalquantity = 0 for cart in cartList: if cart.product_id == cartItem.product_id: found = True totalquantity = cart.quantity + cartItem.quantity cartList.remove(cart) if not found: # 添加字典而非对象 cartList.append(cartItem.to_dict()) else: newItem = CartItem(product_id=cartItem.product_id,name=cartItem.name,image=cartItem.image,quantity=totalquantity,unitprice=cartItem.unitprice,totalprice=totalquantity*cartItem.unitprice) # 添加字典而非对象 cartList.append(newItem.to_dict()) self.cart = [CartItem(**item) for item in cartList] # 保持cart属性为对象列表 self.session[settings.CART_ID] = cartList # 存入字典列表
方法2:使用Django序列化工具(可选)
如果CartItem涉及更复杂的字段,可以使用Django自带的django.core.serializers进行序列化,但对于简单场景,转字典的方式更轻便。
内容的提问来源于stack exchange,提问作者Narayan Banik
相关产品推荐
相关产品推荐

