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

Django JSONField与update_or_create结合时自定义可调用对象序列化异常

问题原因

Django的update_or_create方法对defaults参数中的可调用对象有特殊处理规则:如果值是不带参数的可调用对象,Django会自动调用它,并将返回值作为字段的存储值。你的自定义可调用对象F被识别为可调用类型,因此在执行update_or_create时被触发调用,最终存储的是调用后的字符串,而非预期的序列化对象结构。

解决方案

1. 自定义Model Manager,提前处理可调用对象

创建自定义Manager,在update_or_create执行前,自动将defaults中的F对象转换为序列化后的字典,避免Django调用它:

from django.db import models
from your_module import F, FEncoder

class CustomModelManager(models.Manager):
    def update_or_create(self, defaults=None, **kwargs):
        if defaults:
            # 遍历defaults,将F对象转为序列化字典
            for field, value in defaults.items():
                if isinstance(value, F):
                    defaults[field] = FEncoder().default(value)
        return super().update_or_create(defaults=defaults, **kwargs)

在你的Model中使用这个Manager:

from django.db.models import Model
from your_module import CustomJSONField

class YourModel(Model):
    data = CustomJSONField()  # 你定义的带FEncoder/FDecoder的自定义JSONField
    objects = CustomModelManager()

2. 确保自定义JSONField配置正确

如果还未实现自定义JSONField,需要继承默认JSONField并绑定你的编码器和解码器,确保所有读写操作都遵循自定义序列化逻辑:

from django.db.models import JSONField

class CustomJSONField(JSONField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("encoder", FEncoder)
        kwargs.setdefault("decoder", FDecoder)
        super().__init__(*args, **kwargs)
效果说明

处理完成后,调用update_or_create时无需手动调用to_serializable():

  • Manager会自动将defaults中的F对象转换为序列化字典
  • CustomJSONField会将字典存储为{"class": "F", "val": "1"}格式
  • 读取数据时,FDecoder会自动将字典还原为F对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:07:12