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

Отменить перенаправление 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',
        ),
    ]

Устранение этой миграции исключает исключение:

$ 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

Конечно, это ожидаемое поведение, четко документировано, и я не спрашиваю, почему это происходит:

Имейте в виду, что при обратном это фактически добавляет поле к модель; если поле не является нулевым, это может сделать эту операцию необратимой (кроме потери данных, которая, конечно же, необратимый).

Однако мы все совершаем ошибки, а иногда нам просто нужно, чтобы каким-то образом отменить удаление поля, даже если это означает, что вручную предоставляет значение ad hoc для всех обратных ненулевых полей. Например, южные миграции необязательно позволяют отменить такие операции (попросив разработчика указать, следует ли предоставлять по умолчанию восстановленные поля или запретить обратную миграцию), что, похоже, не относится к всем новым причудливым переходам Django 1.7.

Вопрос: какой самый простой/быстрый способ отменить удаление поля с помощью переноса Django 1.7+ (предположим, что это уже произошло)? Не обязательно полностью писать сценарии с помощью Python, будет выполнен набор ручных инструкций.

4b9b3361

Ответ 1

Вы можете вручную изменить свою миграцию и добавить 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,
    ),

Ответ 2

Если вы пытаетесь сделать будущие миграции обратимыми, вы можете попробовать удалить поле в виде трех миграций.

  • Сделать поле нулевым.
  • Перенос данных. Вперед, ничего не делай. Обратно, конвертируйте нули в значение заглушки.
  • Удалить поле

Каждый из этих трех шагов должен быть обратимым.

Если вы уже выполнили миграцию и вам нужно отменить ее, вы можете

  • вручную добавьте поле, допустив nulls
  • конвертировать нули в значение заглушки
  • вручную добавить ограничение, отличное от нуля
  • Перенести с --fake в предыдущую миграцию