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

为何不同含JSONField的Django Model实例值异常相同?

问题原因分析与解决方案

你碰到的这个情况其实是Django模型字段使用可变对象作为默认值时的一个常见陷阱,我来给你拆解一下:

核心原因

你给JSONField设置的默认值是一个可变的字典对象{'name':'Model'},而Django在初始化模型字段默认值时,对于可变对象并不会每次创建新实例——所有新生成的Mod对象,都会共享同一个字典的引用。

也就是说:

  • 创建m1时,它的data指向了这个默认字典;
  • 创建m2时,并没有生成新的字典,而是和m1共享了同一个引用;
  • 当你修改m2.data['name']时,其实是直接修改了那个被共享的字典,所以内存里的m1.data也跟着变成了'Model 2';
  • 但m1已经提前保存到数据库了,数据库里存储的是最初的默认值,所以从数据库重新获取m1a时,拿到的是正确的原始数据。

解决方法

要解决这个问题,关键是让每个新实例都拿到独立的默认字典,而不是共享引用,常用的两种方式:

方式一:使用lambda函数作为默认值

这是最简洁的方式,lambda会在每次创建新实例时返回一个新的字典:

from django.db import models
from django.contrib.postgres.fields import JSONField

class Mod(models.Model):
    data = JSONField(default=lambda: {'name':'Model'})

方式二:自定义可调用函数返回默认值

如果默认值的逻辑更复杂,可以写一个单独的函数,然后把它作为默认值:

from django.db import models
from django.contrib.postgres.fields import JSONField

def get_default_data():
    # 这里可以添加更复杂的默认值生成逻辑
    return {'name':'Model'}

class Mod(models.Model):
    data = JSONField(default=get_default_data)

注意这里不要加括号,直接传函数本身,Django会在需要时自动调用它生成新的默认值。

额外提醒

不止JSONField,所有Django模型字段如果使用**可变对象(比如列表、字典)**作为默认值,都会出现类似的引用共享问题,这是Python和Django的默认值处理机制决定的,属于必须规避的开发陷阱哦。

内容的提问来源于stack exchange,提问作者Jeremy S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:35:43