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

Django3.2使用F()自增字段触发DeserializationError错误如何解决?

报错原因

这个错误和你传入的整数1没有任何关系,问题根源在F表达式的运行逻辑和第三方审核模块(moderation)的信号执行顺序冲突:

  1. F表达式本质是SQL表达式的Python封装,你给view_count赋值F('view_count') + 1之后,存在当前实例属性上的不是计算后的整数值,而是CombinedExpression表达式对象,这个对象只有在save执行时才会被转换成SQL语句,交由数据库层面完成计算和存储。
  2. 你原本的逻辑save之后调用refresh_from_db是正确的,本来可以把数据库中计算完成的整数值拉回实例,覆盖掉之前的表达式对象。但从栈追踪可以明显看到:save执行过程中会触发post_save信号,你使用的moderation模块的post_save_handler逻辑会在refresh_from_db执行前,就尝试读取当前实例的view_count字段做序列化,拿到的还是未计算的表达式对象,自然无法转成整数,就抛出了反序列化错误。

你调试时看到save执行后字段还是表达式对象是正常现象,只要没有其他逻辑在刷新前读取这个字段,就不会出问题,Django官方文档的用法是完全正确的。

解决方案

最优方案:直接用QuerySet的update方法更新(推荐)

完全绕开实例save流程,既保留F表达式的原子性避免竞态条件,也不会触发当前实例的post_save信号,从根源规避冲突:

def __update_fields(self, interaction_type):
    update_fields = {}
    if interaction_type == Engagement.VIEW:
        update_fields['view_count'] = F('view_count') + 1
    # 其他要更新的字段同理加入update_fields
    
    if update_fields:
        # 直接在数据库层执行更新,原子操作
        self.__class__.objects.filter(pk=self.pk).update(**update_fields)
        # 刷新实例获取最新值
        self.refresh_from_db()

备选方案:跳过moderation模块的本次审核逻辑

如果业务要求必须走实例save流程,可以根据你使用的moderation模块的文档,给save方法加跳过审核的参数,大部分主流moderation库都支持这类配置,比如django-moderation可以加skip_moderation=True参数:

self.save(skip_moderation=True)
# 后续再执行refresh_from_db

兜底方案:保存前指定update_fields

如果上述方案都不适用,可以在save时明确指定只更新计数字段,减少不必要的信号逻辑触发:

self.save(update_fields=['view_count'])
self.refresh_from_db()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:27:01