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

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对象。

  1. 给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
        }
  1. 修改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 = []
    # 其他方法不变
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:34:52