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

Django存储订单到会话时Product对象无法JSON序列化问题求解

问题根因分析

该报错的核心原因是Django 2.1及以上版本默认使用JSONSerializer作为会话序列化器,无法直接序列化自定义的Product模型实例。购物车同类操作没有触发报错的原因通常为以下两点:

  • 你此前实现Basket类时,存入会话的仅为商品ID、价格、数量等基础类型数据,仅在读取购物车时通过ID查询Product实例做前端展示,没有直接把Product实例存入会话
  • 新开发的Orders类逻辑中,直接将Product模型实例放入了待存入会话的订单数据结构中,触发JSON序列化失败
可行解决步骤

方案1:调整订单存储逻辑(推荐,和现有购物车逻辑对齐)

不要在订单条目中直接存储Product实例,仅存入可被JSON序列化的基础字段,同时建议存储商品信息快照,避免后续商品信息修改导致历史订单显示异常:

# 错误写法示例
order_items.append({
    "product": product_instance, # 直接存Product实例触发报错
    "count": item_count,
    "subtotal": item_subtotal
})

# 修正后写法
order_items.append({
    "product_id": product_instance.id,
    "product_name": product_instance.name,
    "product_price": str(product_instance.price),
    "count": item_count,
    "subtotal": str(item_subtotal)
})

后续读取订单数据时,如果需要获取完整Product实例,用存储的product_id查询数据库即可;如果仅做历史订单展示,直接读取已经存储的快照字段即可,无需额外查库。

方案2:自定义模型序列化方法

给Product模型新增序列化方法,将实例转换为可JSON序列化的字典后再存入会话:

class Product(models.Model):
    # 原有模型字段定义
    name = models.CharField(max_length=128)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    # 其他字段...

    def serialize(self):
        return {
            "id": self.id,
            "name": self.name,
            "price": str(self.price)
        }

存入订单时调用该方法替换直接存实例即可:"product": product_instance.serialize()

方案3:切换会话序列化器(不推荐生产环境使用)

如果仅为临时测试,可以把Django会话序列化器换回旧版的Pickle序列化器,修改settings.py配置:

SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'

该方案存在远程代码执行的安全风险,若会话数据被篡改可能导致服务器被攻击,仅可用于本地测试场景,禁止生产环境使用。

注意事项
  • Decimal、datetime等特殊类型存入会话前需要提前转换为字符串/数字类型,否则也会触发序列化报错
  • 历史订单数据建议优先存快照信息,不要依赖实时数据库查询,避免商品删除、修改后历史订单显示异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:48:00