In Django 1.9, what's the convention for using JSONField (native postgres jsonb)?

戏子无情 提交于 2019-12-09 02:12:21

问题


Django highly suggests not to use null=True for CharField and TextField string-based fields in order not to have two possible values for "no data" (assuming you're allowing empty strings with blank=True). This makes total sense to me and I do this in all my projects.

Django 1.9 introduces JSONField, which uses the underlying Postgres jsonb data type. Does the suggestion above carry over to JSONField (i.e. blank=True should be used instead of null=True)? Or, should null=True be used instead? Or, should default=dict be used instead? Or, ..? Why?

In other words, what is the convention for the new native JSONField, when you want to allow only one "no data" value? Please support your answer because I did a lot of research and couldn't find anything official. Thanks in advance.


回答1:


The convention implied from the Django code seems to be to store null JSON values as NULL as opposed to as an empty string (as is the convention for the CharField). I say this because of the following:

The empty_strings_allowed is inherited from Field in CharField, and is set to 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, however, overrides it with False:

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

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

This causes CharField's to default to "" and JSONField's to None when you instantiate a model without explicitly passing the values for these fields.

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 ""

Therefore, if you want to make a JSONField optional, you have to use:

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

If you use only blank=True, as you would for CharField, you'll get an IntegrityError when trying to run MyModel.objects.create(...) without passing a json_field argument explicitly.




回答2:


Just wanted to add that you should avoid setting default values on JSONField. I just made a schoolboy error by setting it to {}. The result is that new objects will receive the last object's value if it was not explicitly set. Its a Python behaviour inherent in the JSONField, which I forgot to consider.



来源:https://stackoverflow.com/questions/36209336/in-django-1-9-whats-the-convention-for-using-jsonfield-native-postgres-jsonb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!