Правильное объявление пустого значения DJango PostgreSQL JSONField по умолчанию в файле миграции - PullRequest
0 голосов
/ 01 июня 2018

Я немного растерялся, интерпретируя Объяснение Django применения значения по умолчанию к JSONField PostgreSQL:

Если вы задаете для поля значение по умолчанию, убедитесь, что оно вызывается, напримеркак dict (для пустого значения по умолчанию) или как вызываемое, которое возвращает dict (например, функцию).Неправильное использование default={} создает изменяемое значение по умолчанию, которое используется всеми экземплярами JSONField.

Поэтому в моем файле модели я объявил значение по умолчанию как таковое

foo = JSONField(default=dict())

когда я генерирую операцию переноса для нового поля, это результат

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

Я просто не уверен, соответствует ли этот результат предложению документации.Это допустимо, или я должен изменить сгенерированный по умолчанию вызов dict()?

1 Ответ

0 голосов
/ 01 июня 2018

A callable - это объект x, который может быть вызван, следовательно, x() допустим и не вызовет ошибку, потому что он не вызывается (хотя можетошибки во время вызова, например, потому что функция где-то выдает ошибку).

dict() на самом деле полностью эквивалент до {}, что не вызывается, так как {}(), не приведет к созданию чего-либо.Но с другой стороны, dict является ссылкой на класс dict, и если мы его назовем, мы создадим new dict.Поэтому мы должны написать это следующим образом:

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

Итак, мы не вызываем класс dict, мы передаем ссылку в класс и такие классыявляются вызываемыми: если вы вызываете их, вы, как правило, создаете новый экземпляр (хотя это поведение можно изменить).

Передача вызываемого элемента имеет жизненно важное значение, поскольку в противном случае Django будет каждый раз использовать ссылку на такой же словарь.В результате изменения одного из словарей изменят другие, которые изменят ссылку.Если вы сохраните словарь и перезагрузите его, то это будет другой словарь, но если вы построили две модели во время одного и того же запуска Python, это будут одни и те же объекты.

Если вы, однако, передадитефункция, функция будет вызвана, и, таким образом, создаст два разных объекта, оба пустых словаря.Но изменения в первом словаре не отразятся во втором.

То же самое верно, если, например, вы захотите инициализировать поле 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>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...