Можно ли воссоздать поле таблицы, которое было случайно удалено из Django Model, не снося все миграции?

Предположим следующую модель:

class Country(models.Model):
    name = models.TextField(null=True, blank=True)
    continent = models.TextField(null=True, blank=True)
    population = models.PositiveIntegerField(null=True, blank=True) 

И тогда я:

  1. Delete the field population from models.py.
  2. Create a migration: python manage.py makemigrations countries_app
  3. Execute the migration, which marks the field as removed: python3 manage.py migrate countries_app

Вот файл миграции 0006, который является последовательностью для последней созданной миграции (0005):

class Migration(migrations.Migration):

    dependencies = [
        ('countries_app', '0005_auto_20210723_0007'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='country',
            name='population',
        ),
    ]

Теперь у меня нет поля population в моей базе данных, но я понял, что это была ошибка, удалить поле population из Country модели.

Пытаясь вернуть все на свои места, я снова определяю поле на модели и отменяю миграцию 0006, а также удаляю 0006 файл миграции, где было определено удаление поля, а также выполняю python manage.py migrate countries_app и он говорит nothing to migrate, что имеет смысл.

$ python3 manage.py migrate countries_app
Operations to perform:
  Apply all migrations: countries_app
Running migrations:
  Applying countries_app.0006_remove_country_population... OK

$ rm countries_app/migrations/0006_remove_country_population.py

$ python manage.py migrate countries_app

Но когда я проверяю таблицу базы данных, поле population по-прежнему отсутствует. Я думал, что Django создаст его заново, поскольку я отменил миграцию 0006 и поле снова было определено в моей модели.

Я видел некоторые ответы здесь на SO, в которых говорилось что-то вроде: отменить все миграции (python manage.py migrate countries_app zero), удалить все файлы миграции, создать начальную миграцию еще раз и затем выполнить миграцию.

Это звучит слишком жестоко для меня. Я бы хотел поручить Django воссоздать поле, которого больше нет. Есть ли какой-нибудь эффективный и более щадящий способ сделать это? Я не настолько продвинут в Django Migrations, поэтому, пожалуйста, потерпите меня. Спасибо.

Конечно, вы можете добавить поле обратно в модель и снова использовать makemigrations, а затем выполнить миграцию вперед (0006 -> 0007). Это определит столбец обратно в базу данных, но вам придется заново заполнить его действительными данными. Простая миграция просто заполнит его значением по умолчанию.

После некоторого исследования и тестирования, технически, отменяя миграцию 0006 (откатываясь к 0005), Django воссоздает поле, которое когда-то было удалено. Я провел локальные тесты в другом проекте, и да, это правда.

Почему откат к миграции 0005 не сработал в моем случае, неизвестно. Возможно, я что-то напутал в своем реальном проекте. Поэтому в качестве ответа я заявляю, что откат к предыдущей миграции - это обычно то, что вам нужно в таких случаях.

Но, если все действительно запутано и Django не воссоздает поле, которое когда-то было удалено, а теперь снова появилось в вашей модели, я вижу 2 альтернативы:

  1. Ответ Nigel222. Это будет работать, но все же, принесет дополнительную миграцию, только для воссоздания поля.

  2. Подключитесь к базе данных и вручную создайте поле. Это исправит произошедшую аномалию, и не будет дополнительной миграции только для пересоздания поля, которое должно было вернуться обратно при откате миграции:

ALTER TABLE countries_app_country ADD population INTEGER;
Вернуться на верх