如何忽略特定的迁移?

时间:2019-10-23 08:34:29

标签: django django-migrations

我有这样的迁移:

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都会再次添加 迁移(=我的问题顶部的迁移)。我猜这是因为在迁移过程中看不到它,因为我的代码使它变得模糊了。

如何通过迁移来避免这种情况(不要说诸如“此问题在您的数据库中,请更正您的数据库”之类的答案)?

2 个答案:

答案 0 :(得分:1)

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

./manage.py migrate app_name migration_number --fake

这会将迁移标记为已完成。

答案 1 :(得分:1)

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),
        ),
    ]