Примечание:
Я понимаю и хорошо знаю разницу между передачей функции в качестве параметра и вызовом функции и передачей результата в качестве параметра.Мне кажется, я правильно передаю эту функцию.
Спецификации
- Django 1.11
- PostgreSQL 10.4
Сценарий:
У меня в приложении десятки моделей со многими существующими записями.Мне нужно добавить случайное начальное число для каждой из этих моделей, которые будут созданы и установлены при создании нового экземпляра модели.Я также хочу сгенерировать случайное начальное число для существующих экземпляров.
Мое понимание того, как модель Django по умолчанию и Миграции работает, заключается в том, что при добавлении нового поля вмодели, если для этого поля установлено значение по умолчанию, Djano обновит все существующие экземпляры новым полем и соответствующим значением по умолчанию.
Однако, несмотря на то, что я определенно передаю функцию в качестве значения по умолчанию, ифункция генерирует случайное число, Django использует то же случайное число при обновлении существующих строк (например, кажется, что Djano вызывает функцию только один раз, а затем использует возвращаемое значение для всех записей).
Пример
Сокращенная версия моего кода:
def get_random():
return str(random.random())
class Response(models.Model):
# various properties
random = models.CharField(max_length=40, default=get_random)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = JSONField(null=True)
Случайное поле добавляется после модели, и многие ее экземпляры уже созданы.Появляется команда makemigrations
для генерации правильного файла миграции с вызовом migrations.AddField()
, передающим в качестве параметра default=get_random
.
Однако после запуска makemigrations
все существующие существующие экземпляры Response
содержат точно такое же число в их поле random .Создание и сохранение новых экземпляров модели работают должным образом (с псевдо-уникальным случайным числом).
Обходной путь
Простой обходной путь - просто запустить одноразовый скрипт, который выполняет
for r in Response.objects.all():
r.random = get_random()
r.save()
Или переопределите метод save()
модели, а затем выполните массовое сохранение.Но я не думаю, что эти обходные пути должны быть необходимыми.Это также означает, что если я хочу создать уникальное поле со случайным значением по умолчанию, мне потребуется несколько миграций.Сначала я должен добавить поле с назначенным значением по умолчанию.Далее мне нужно применить миграцию и вручную повторно инициализировать значения полей.Затем вторая миграция для добавления свойства unique=True
.
Кажется, что если Django должен применить значения по умолчанию к существующим экземплярам при makemigrations
, то он должен применять их, используя ту же семантику, что и при создании нового экземпляра.Есть ли способ заставить Django вызывать функцию для каждого экземпляра модели при миграции?