Подтвердить что ты не робот

В Django 1.9, что такое соглашение об использовании JSONField (native postgres jsonb)?

Django предлагает вам не использовать null=True для строковых полей CharField и TextField, чтобы не иметь двух возможных значений для "нет данных" (предполагается, что вы разрешаете пустые строки с blank=True). Это дает мне полный смысл, и я делаю это во всех своих проектах.

Django 1.9 вводит JSONField, который использует базовый тип данных Postgres jsonb. Предполагается ли вышеприведенное предложение переносить на JSONField (т.е. blank=True вместо null=True)? Или, вместо null=True? Или, вместо этого следует использовать default=dict? Или,..? Почему?

Другими словами, что такое соглашение для нового родного JSONField, если вы хотите разрешить только одно значение "нет данных"? Пожалуйста, поддержите свой ответ, потому что я провел много исследований и не нашел ничего официального. Спасибо заранее.

4b9b3361

Ответ 1

Предполагается, что соглашение, заключенное в коде Django, хранит значения нуля JSON как NULL, а не пустую строку (как и соглашение для CharField). Я говорю это из-за следующего:

empty_strings_allowed наследуется от Field в CharField и устанавливается в 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 по умолчанию "" и JSONField - None используется экземпляр модели, явно не передавая значения для этих полей.

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, вы получите IntegrityError при попытке запустить MyModel.objects.create(...) без передачи аргумента json_field явно.

Ответ 2

Просто хотел добавить, что вам следует избегать установки значений по умолчанию на JSONField. Я просто сделал ошибку школьника, установив ее на {}. В результате новые объекты получат последнее значение объекта, если оно явно не задано. Его поведение на Python, присущее JSONField, которое я забыл рассмотреть.