恢复Django 1.7 RemoveField迁移

Ily*_*nov 22 django django-south django-1.7 django-migrations

如果我有一个不可为空的模型字段,删除它,并创建一个迁移,那么迁移将变为不可逆:

考虑以下模型:

class Foo(models.Model):
    bar = models.TextField()
    test = models.TextField()  # This field is to go away, bye-bye!
Run Code Online (Sandbox Code Playgroud)

和迁移:

# app/migrations/003_remove_foo_test.py

class Migration(migrations.Migration):

    dependencies = [
        ('app', '0002_foo_test'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='foo',
            name='test',
        ),
    ]
Run Code Online (Sandbox Code Playgroud)

取消应用此迁移会引发异常:

$ 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
Run Code Online (Sandbox Code Playgroud)

当然,这是预期的行为,它是清楚记录的,我不是在问为什么会发生这种情况:

请记住,当反转时,这实际上是在模型中添加一个字段; 如果该字段不可为空,则可能使该操作不可逆转(除了任何数据丢失,这当然是不可逆转的).

但是,我们都会犯错误,有时我们只需要某种方式反转字段删除,即使这意味着手动为所有反转的非空字段提供临时存根值.例如,南迁移可选择允许逆转此类操作(通过询问开发人员是否为恢复的字段提供默认值,或禁止反向迁移),这似乎不是所有新奇特的Django 1.7迁移的情况. .

问题:使用Django 1.7+迁移撤消字段删除的最简单/最快方法是什么(假设它已经发生)?它不一定需要用Python完全编写脚本,一组手动指令也可以.

Gwy*_*idD 22

您可以手动编辑迁移,并AlterField为之前的字段添加默认值RemoveField.即使应用迁移后它也应该是安全的.这将使之RemoveField成为可逆之后的事情.

一个例子.在模型中的字段summary名称profit是在删除之前定义的那样:

profit = models.PositiveIntegerField(verbose_name='profits')
Run Code Online (Sandbox Code Playgroud)

你应该在RemoveField它之前添加AlterField如下:

migrations.AlterField(
    model_name='summary',
    name='profit',
    field=models.PositiveIntegerField(verbose_name='profits', default=0),
    preserve_default=False,
    ),
Run Code Online (Sandbox Code Playgroud)

  • 我能够使用`preserve_default = True`在Django 1.8中使用它. (4认同)
  • 它似乎不适用于`ForeignKey`字段.:( (2认同)

Ala*_*air 5

如果您尝试使未来的迁移可逆,您可以尝试将该字段作为三个迁移删除。

  1. 使字段可为空
  2. 数据迁移。向前走,什么也不做。向后,将 null 转换为存根值。
  3. 删除该字段

这三个步骤中的每一个都应该是可逆的。

如果您已经运行迁移并需要撤消它,您可以

  1. 手动添加字段,允许空值
  2. 将 null 值转换为存根值
  3. 手动添加非空约束
  4. 迁移--fake到之前的迁移