如何忽略特定的迁移?

How to ignore a specific migration?

我有这样的迁移:

class Migration(migrations.Migration):

    dependencies = [
        ('app', '0020_auto_20191023_2245'),
    ]

    operations = [
        migrations.AddField(
            model_name='agenda',
            name='theme',
            field=models.PositiveIntegerField(default=1),
        ),
    ]

但是它引发了一个错误:

django.db.utils.ProgrammingError: column "theme" of relation "app_agenda" already exists

没问题,我已经像这样包装了这个错误:

from django.db import migrations, models, ProgrammingError


def add_field_theme_to_agenda(apps, schema_editor):
    try:
        migrations.AddField(
            model_name='agenda',
            name='theme',
            field=models.PositiveIntegerField(default=1),
        ),
    except ProgrammingError as e:  # sometimes it can exist
        if "already exists" not in str(e):
            raise


class Migration(migrations.Migration):
    dependencies = [
        ('app', '0020_auto_20191023_2245'),
    ]
    operations = [
        migrations.RunPython(add_field_theme_to_agenda),
    ]

这很有用,接下来的所有迁移都已完成。

我的问题是每次我 运行 一个“makemigrations” Django 添加 again 迁移(= 我的问题顶部的那个).我想这是因为它在迁移中看不到它,因为我的代码混淆了它。

如何使用迁移来规避此问题(不要说 "this problem is on your database, correct your database" 之类的答案)?

您可以在迁移命令中利用 --fake 标志

./manage.py migrate app_name migration_number --fake

这会将迁移标记为完成。

Django 正在重新创建迁移,因为当您在 RunPython 操作中手动执行操作时,它无法理解添加的字段。您可以尝试的是(我自己还没有尝试过),将 AddField 操作子类化以创建自定义 AddField 操作,您可以在其中处理异常。像下面这样的东西可以工作:

from django.db import migrations, models, ProgrammingError


class AddFieldIfNotExists(migrations.AddField):

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        try:
            super().database_forwards(app_label, schema_editor, from_state,
                                      to_state)
        except ProgrammingError as e:  # sometimes it can exist
            if "already exists" not in str(e):
                raise


class Migration(migrations.Migration):
    atomic = False
    dependencies = [
        ('app', '0070_auto_20191023_1203'),
    ]

    operations = [
        AddFieldIfNotExists(
            model_name='agenda',
            name='theme',
            field=models.PositiveIntegerField(default=1),
        ),
    ]