【问题标题】:In Django 1.9, what's the convention for using JSONField (native postgres jsonb)?在 Django 1.9 中,使用 JSONField(本机 postgres jsonb)的约定是什么?
【发布时间】:2016-03-24 20:21:32
【问题描述】:

Django highly suggests notnull=True 用于基于字符串的 CharField 和 TextField 字段,以便没有两个可能的“无数据”值(假设您允许使用空字符串blank=True)。这对我来说很有意义,我在所有项目中都这样做。

Django 1.9 引入了JSONField,它使用底层的 Postgres jsonb 数据类型。上述建议是否适用于 JSONField(即应使用 blank=True 而不是 null=True)?或者,应该改用null=True 吗?或者,应该改用default=dict 吗?或者, ..?为什么?

换句话说,当您只想允许一个“无数据”值时,新的原生 JSONField 的约定是什么?请支持您的回答,因为我做了很多研究,但找不到任何官方信息。提前致谢。

【问题讨论】:

  • 在阅读完文档后,我敢打赌 null=True 是最好的,因为 JSONField 应该是一个有效的对象,并且通常“空”对象使用 null 分配来表明这一点。只是我的 2c。

标签: python json django postgresql jsonb


【解决方案1】:

Django 代码暗示的约定似乎是将空 JSON 值存储为 NULL,而不是空字符串(CharField 的约定也是如此)。我之所以这样说是因为:

empty_strings_allowed 继承自 CharField 中的 Field,并设置为 True

django/db/models/fields/__init__.py#L96

class Field(RegisterLookupMixin):
    """Base class for all field types"""

    # Designates whether empty strings fundamentally are allowed at the
    # database level.
    empty_strings_allowed = True
    ...

JSONField 然而,用False 覆盖它:

django/contrib/postgres/fields/jsonb.py#L13

class JSONField(Field):
    empty_strings_allowed = False
    ...

当您在未显式传递这些字段的值的情况下实例化模型时,这会导致 CharField 默认为 ""JSONFieldNone

django/db/models/fields/init.py#L791

def get_default(self):
    """
    Returns the default value for this field.
    """
    if self.has_default():
        if callable(self.default):
            return self.default()
        return self.default
    if (not self.empty_strings_allowed or (self.null and
               not connection.features.interprets_empty_strings_as_nulls)):
        return None
    return ""

因此,如果你想让JSONField 成为可选的,你必须使用:

json_field = JSONField(blank=True, null=True)

如果您只使用blank=True,就像使用CharField 一样,在尝试运行MyModel.objects.create(...) 而不显式传递json_field 参数时,您将获得IntegrityError

【讨论】:

    【解决方案2】:

    只是想补充一点,您应该避免在 JSONField 上设置默认值。我刚刚通过将其设置为{} 犯了一个小学生错误。结果是,如果没有明确设置,新对象将接收最后一个对象的值。它是 JSONField 中固有的 Python 行为,我忘记考虑了。

    【讨论】:

    • 您无需避免默认设置。发生此问题是因为您提供了一个可变对象作为默认值。您应该提供可调用的dict 而不是{}。检查docs:“如果您为该字段提供默认值,请确保它是可调用的,例如 dict(对于空默认值)或返回 dict 的可调用(例如函数)。错误地使用 default={} 创建一个在 JSONField 的所有实例之间共享的可变默认值。"
    猜你喜欢
    • 2016-08-07
    • 2016-08-28
    • 2016-05-30
    • 1970-01-01
    • 2019-07-30
    • 2018-10-19
    • 2015-12-24
    • 2018-09-29
    • 1970-01-01
    相关资源
    最近更新 更多