python - 在迁移文件中正确声明空 Django PostgreSQL JSONField 默认值

标签 python django postgresql

我有点迷失了解释 Django's将默认值应用于 PostgreSQL JSONField 的说明:

If you give the field a default, ensure it’s a callable such as dict (for an empty default) or a callable that returns a dict (such as a function). Incorrectly using default={} creates a mutable default that is shared between all instances of JSONField.

所以在我的模型文件中我声明了默认值

foo = JSONField(default=dict())

然而,当我为新字段生成迁移操作时,这就是结果

migrations.AddField(
    model_name='bar',
    name='foo',
    field=django.contrib.postgres.fields.jsonb.JSONField(default={}))

我只是不确定这个结果是否符合文档的建议。这是有效的,还是我应该修改生成的默认值以调用 dict()

最佳答案

callable 是一个 x 对象,可以 调用,因此 x() 是有效的,并且不会引发错误,因为它不可调用(尽管在调用期间可能会出现错误,例如因为某处的函数产生错误)。

dict() 实际上完全等同于 {},它不是可调用的,因为 {}(),不会导致构建任何东西。但另一方面,dict 本身是对 dict 类的引用,如果我们调用它,我们将构造一个 字典。所以我们应该这样写:

# no brackets! We do not make a call, but pass the callable
foo = JSONField(default=<b>dict</b>)

所以我们调用dict类,我们传递一个引用给类,这样的类是可调用的:如果你调用它们,您通常会构造一个新实例(尽管可以更改此行为)。

传递可调用对象在这里至关重要,否则 Django 每次都会使用对相同字典的引用。结果,对其中一个词典的更改将更改其他更改引用的词典。如果您存储字典并重新加载它,那么这将是一个不同的字典,但只要您构建了两个模型,在同一 Python 运行期间,它们将是相同的对象。

但是,如果您传递一个函数,该函数将被调用,从而产生两个不同 对象,它们都是空字典。但是对第一个字典的更改不会反射(reflect)在第二个字典中。

例如,如果您想要使用包含数据的字典来初始化 JSON 字段,而不是编写 default={'a': 4},这同样适用, 必须这样定义它:

def <b>default_somemodel_dict</b>():
    return {'a': 4}

class SomeModel(models.Model):
    foo = JSONField(default=<b>default_somemodel_dict</b>)

关于python - 在迁移文件中正确声明空 Django PostgreSQL JSONField 默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50632721/

相关文章:

python - Flask Assets 仅在一个文件中查找更改

python - 在 django orm 查询中指定 sql 表达式作为列名

python - 403 - CSRF token 丢失或不正确

sql - 使用 Bookshelf 对 Postgres JSONB 数组元素执行查询

macos - mac 上删除了 PostgreSQL 用户,如何恢复?

database - 违反唯一约束的行

python - nose 框架命令行正则表达式模式匹配不起作用(-e,-m,-i)

Python ARIMA 预测返回 NaN

python - 列表中元素的识别 - 机器学习

Django自定义加载外键