Как игнорировать конкретную миграцию? - PullRequest
0 голосов
/ 23 октября 2019

У меня есть такая миграция:

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 ]

1 голос
/ 23 октября 2019

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),
        ),
    ]
1 голос
/ 23 октября 2019

Вы можете воспользоваться флагом --fake в команде переноса

./manage.py migrate app_name migration_number --fake

Это пометит миграцию как выполненную.

...