Django 1.8 Migrations. Добавление DateTimeField после создания db. Лучшие практики?

Итак, некоторое время после нескольких миграций после моего первого, я решил включить эти поля:

created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)

в одну из моих моделей. Когда я давал мне makemigrations, You are trying to add a non-nullable field 'created' to episode without a default; we can't do that (the database needs something to populate existing rows). You are trying to add a non-nullable field 'created' to episode without a default; we can't do that (the database needs something to populate existing rows).

Поэтому я изменил его на

created = models.DateTimeField(auto_now_add=True, default=datetime.now)

После повторной makemigrations повторить, он сказал, что at_api.Episode.modified: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present. at_api.Episode.modified: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.

Хорошо, поэтому я просто пошел вперед и удалил auto_now_add

created = models.DateTimeField(default=datetime.now)

Теперь я мог makemigrations без makemigrations проблем. И затем я позже удалил default=datetime.now и заменил его на auto_now_add=True и снова перенастроил без каких-либо проблем. Однако я не могу не чувствовать, что это может быть не лучший способ сделать что-то. Я чувствую, что что-то может пойти не так позже в проекте.

Ответ 1

Я думаю, что лучшая практика здесь заключалась бы в том, чтобы сделать поля обнуляемыми. То, что created ваше поле, означает: "Время создания экземпляра или произвольное время, когда я запускал миграцию". Стандартный способ представления отсутствия значения - NULL, а не произвольное значение.

Тем не менее, если вы хотите использовать какое-то произвольное значение, вам просто нужно сказать Django, что это такое. Обычно makemigrations дает вам возможность указывать одноразовое значение для использования для существующих строк - не произошло ли это?

Более трудоемким методом было бы объявить поле нулевым, затем создать миграцию данных, чтобы заполнить нужное значение, а затем сделать его недействительным. То, что вы сделали, в основном упрощенная версия. Я не вижу, чтобы это создавало какие-либо проблемы, перемещаясь вперед, кроме проблемы created самом деле не являющегося временем создания экземпляра.

Ответ 2

У меня точно была проблема. Я использую Django 1.10. Я прочитал ответ Кевина, и я попытался установить значение по умолчанию, когда Django попросил меня заполнить его как строку datetime.now. И я был удивлен, потому что для этих полей Django автоматически спрашивает вас, хотите ли вы использовать datetime.now по умолчанию:

$ ./manage.py makemigrations
You are trying to add the field 'date_created' with 'auto_now_add=True' to projectasset without a default; the database needs something to populate existing rows.

 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
You can accept the default 'timezone.now' by pressing 'Enter' or you can provide another value.
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
[default: timezone.now] >>>

Итак, я просто подтверждаю это, и все работает нормально!