You need to enable JavaScript to run this app. Django request.session存多会话项触发Product不可JSON序列化报错
优惠活动
大模型
产品
解决方案
定价
更多

Django request.session存多会话项触发Product不可JSON序列化报错

问题复现与场景说明

在Django项目request.session中原有字典结构的cart会话项,长期运行无异常。新增整数类型的com_order_id会话项后,程序触发类型错误:

TypeError at ...
Object of type Product is not JSON serializable

触发报错的会话数据样例:

{
    'com_order_id': 59,
    'cart': {
        '3': {
            'quantity': 1,
            'product': <Product: Christmas With Prestige>,
            'total_price': 30000,
            'total_weight': Decimal('2.30')
        }
    }
}

实测验证:仅保留cart会话项、或仅保留com_order_id会话项时,程序均可正常运行;只有两项同时存储时,才会触发上述序列化报错。

核心报错原因

Django默认会话序列化器的分支判断逻辑存在兼容缺陷:

  • 序列化器会根据会话内容自动选择存储路径:标准JSON序列化路径仅支持整数、字符串、字典、列表等原生Python类型;Pickle序列化路径支持任意Python对象的序列化
  • 默认序列化器的JSON兼容性判断仅校验会话顶层数据的类型,不会递归校验嵌套结构的可序列化性
  • 单独存储cart时,会话顶层值本身是包含不可序列化对象的嵌套结构,序列化器会正确回退到Pickle路径,因此运行正常
  • 单独存储com_order_id整数时,会话全量内容均为JSON兼容的原生类型,直接走JSON序列化路径,因此运行正常
  • 两项数据同时存储时,序列化器检测到顶层存在com_order_id这类JSON兼容的原生类型,就判定整个会话可走JSON序列化路径,没有递归发现cart嵌套结构内的Product模型实例、Decimal类型这类JSON不可序列化对象,直接执行JSON序列化流程,最终触发类型错误。
可行解决方案
  • 优化购物车的会话存储结构,不直接存放模型实例
    会话存储本身设计为保存轻量可序列化数据,直接存放Product模型实例本身就不符合会话的使用规范。可以将cart内存储的Product实例替换为对应的产品ID,后续业务需要用到产品详情时,再通过ID从数据库查询。同时将Decimal类型的价格、重量值转成整数(以最小货币单位存储价格、以克为单位存储重量),完全适配JSON序列化规则。改造后的购物车结构示例:
    {
        '3': {
            'quantity': 1,
            'product_id': 3,
            'total_price': 30000, # 整数存储,单位为分
            'total_weight': 2300 # 整数存储,单位为克
        }
    }
    
  • 强制指定会话序列化器为PickleSerializer
    在项目settings.py中补充配置,强制全量会话走Pickle序列化路径,绕过默认的自动分支判断逻辑,适配任意Python对象的存储需求:
    SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
    
    需注意该方案的安全风险:Pickle序列化的数据如果被恶意篡改,可能触发反序列化漏洞,仅适合内网、可控场景使用。
  • 自定义带异常捕获的会话序列化器
    基于默认的序列化逻辑做扩展,在JSON序列化执行失败时自动捕获异常并回退到Pickle序列化,兼容两类数据的混合存储场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 03:54:04