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

Django迁移文件中PostgreSQL JSONField空默认值的正确声明疑问

Django PostgreSQL JSONField 默认值迁移代码的疑问解决

你遇到的这个问题正好戳中了Django中可变默认值的经典陷阱,咱们一步步理清楚:

你的迁移代码为什么不符合文档建议?

Django文档反复强调JSONField的默认值必须是可调用对象,而你模型里写的default=dict()和迁移里生成的default={}本质上是同一个问题:它们都是已经实例化的空字典对象。

Python里的可变对象(比如字典、列表)作为默认值时,会被所有类实例共享。也就是说,如果你创建了两个bar实例,它们的foo字段会指向同一个字典——当你修改其中一个实例的foo时,另一个实例的foo也会跟着变,这绝对是你不想看到的隐形bug。

而Django生成迁移时,会把你传入的dict()结果(一个空字典)直接序列化,所以迁移里就变成了default={},和直接写default={}没有任何区别,完全踩了文档警告的坑。

正确的写法是什么?

核心原则是:传递可调用对象本身,而不是它的执行结果。

  1. 空字典默认值的最简写法
    直接用dict(这是一个可调用的类型对象),每次创建新实例时,Django会自动调用dict()生成一个全新的空字典:

    foo = JSONField(default=dict)
    

    对应的迁移代码会变成:

    migrations.AddField(
        model_name='bar',
        name='foo',
        field=django.contrib.postgres.fields.jsonb.JSONField(default=dict),
    )
    
  2. 自定义结构的默认值
    如果需要默认值是带有初始键值对的字典,就写一个自定义函数,传递函数名(不要加括号调用):

    def get_default_foo():
        return {"status": "active", "tags": []}
    
    foo = JSONField(default=get_default_foo)
    

已经生成迁移怎么办?

如果迁移还没应用到数据库,建议先回滚这个迁移(用python manage.py migrate <app_name> <previous_migration>),然后修改模型里的默认值写法,重新生成迁移文件。如果已经应用了,那需要生成一个新的迁移来修正默认值,确保后续创建的实例使用正确的可调用默认值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:50:09