Отменить миграцию Django 1.7 RemoveField
Если у меня есть ненулевое поле модели, удалите его и создайте миграцию, эта миграция станет необратимой:
рассмотрим следующую модель:
class Foo(models.Model):
bar = models.TextField()
test = models.TextField() # This field is to go away, bye-bye!
и миграции:
# app/migrations/003_remove_foo_test.py
class Migration(migrations.Migration):
dependencies = [
('app', '0002_foo_test'),
]
operations = [
migrations.RemoveField(
model_name='foo',
name='test',
),
]
Unapplying эта миграция вызывает исключение:
$ src/manage.py migrate app 0002
Operations to perform:
Target specific migration: 0002_foo_test, from app
Running migrations:
Unapplying app.0003_remove_foo_test...Traceback (most recent call last):
...
django.db.utils.IntegrityError: column "test" contains null values
конечно, это ожидаемое поведение, это четко документированы и я не спрашиваю, почему это происходит:
имейте в виду, что при реверсировании это фактически добавление поля модель; если поле не является nullable это может сделать эту операцию необратимый (помимо любой потери данных, которая, конечно, необратимый.)
тем не менее, мы все делаем ошибки, и иногда мы просто нужно to как-то отменить удаление Поля, даже если это означает ручное предоставление специального заглушки для всех отмененных ненулевых полей. Например, миграция на юг при необходимости позволяет такие операции (путем запроса разработчика о том, следует ли предоставить значение по умолчанию для восстановленных полей или запретить обратную миграцию), что, похоже, не относится ко всем новым миграциям fancy Django 1.7.
вопрос: каков самый простой/быстрый способ отменить удаление Поля с помощью миграции Django 1.7+ (если это уже произошло)? это не обязательно должно быть полностью сценарий с Python, набор ручных инструкций будет делать.
2 ответов
вы можете вручную отредактировать миграцию и добавить AlterField
со значением по умолчанию для поля непосредственно перед RemoveField
. Он должен быть безопасным даже после применения миграции. Это сделает RemoveField
это произойдет после того, чтобы быть обратимым.
пример. Наличие поля в модели summary
имени profit
это было определено перед удалением, как это:
profit = models.PositiveIntegerField(verbose_name='profits')
вы должны добавить перед RemoveField
сюда AlterField
вот так:
migrations.AlterField(
model_name='summary',
name='profit',
field=models.PositiveIntegerField(verbose_name='profits', default=0),
preserve_default=False,
),
Если вы пытаетесь сделать будущие миграции обратимыми, вы можете попробовать удалить поле как три миграции.
- сделать поле nullable
- миграция данных. Вперед, ничего не делай. В обратном порядке преобразуйте нули в заглушку.
- удалить поля
каждый из этих трех шагов должен быть обратимым.
Если вы уже выполнили миграцию и вам нужно ее отменить, вы можете
- вручную добавьте поле, разрешив nulls
- преобразование нулей в значение заглушки
- вручную добавьте ограничение not null
- миграция с
--fake
к предыдущей миграции