В этой статье я расскажу, как решить ошибку InconsistentMigrationHistory при выполнении миграции. Хотя очистка вашей базы данных — это решение, оно не идеально, особенно если вы работаете в среде, отличной от разработки. Вот как это сделать безопасно.

Ошибка

Эта ошибка иногда возникает, если вы выполняете миграцию:

$ ./manage.py migrate
Traceback (most recent call last):
  File "<my_project>/./manage.py", line 22, in <module>
    main()
  File "<my_project>/./manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/base.py", line 106, in wrapper
    res = handle_func(*args, **kwargs)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/core/management/commands/makemigrations.py", line 156, in handle
    loader.check_consistent_history(connection)
  File "<my_project>/.venv/lib/python3.10/site-packages/django/db/migrations/loader.py", line 327, in check_consistent_history
    raise InconsistentMigrationHistory(
django.db.migrations.exceptions.InconsistentMigrationHistory: Migration socialaccount.0001_initial is applied before its dependency sites.0001_initial on database 'default'.

В данном случае это связано с тем, что я установил и перенес приложение socialaccount до того, как добавил django.contrib.sites в INSTALLED_APPS .

Я уже развернул это в рабочей среде, поэтому не хотел выполнять очистку базы данных.

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

Войдите в dbshell

Войдите в оболочку БД. Моя база данных PostgreSQL. Если вы используете что-то другое, убедитесь, что запросы преобразованы соответствующим образом.

$ ENV_FILE=../.env.staging ./manage.py dbshell

Сначала создайте резервную копию таблицы миграции.

CREATE TABLE bak1_django_migrations AS SELECT * FROM django_migrations;

Давайте посмотрим, какие миграции уже применяются.

> SELECT DISTINCT(app) FROM django_migrations WHERE app IN ('socialaccount', 'sites');
       app
-------------------
  socialaccount

Да, как и ожидалось, похоже, что socialaccount было применено, но не sites.

Теперь мы собираемся удалить миграцию socialccount. Помните, как мы делали резервную копию ранее? Если нет, сделайте это в первую очередь. Это всего лишь одна команда копирования и вставки. Просто сделай это.

Итак, об удалении:

DELETE FROM django_migrations WHERE app = 'socialaccount';

Также удалите таблицы. Если в ваших таблицах есть данные, создайте их резервную копию. В этом случае (поскольку socialaccount имеет реляционные таблицы) мне нужно было удалить несколько:

DROP TABLE socialaccount_socialapp;
DROP TABLE socialaccount_socialaccount CASCADE;

Если в ваших таблицах были данные, не беспокойтесь (я имею в виду, что вы не сделали резервную копию своих таблиц). Мы восстановим данные через некоторое время.

Наша миграция должна быть успешной сейчас

Теперь наша миграция должна завершиться успешно:

$ ENV_FILE=../.env.staging ./manage.py migrate
using ENV_PATH <env_path>
System check identified some issues:

Operations to perform:
  Apply all migrations: ....
Running migrations:
  Applying sites.0001_initial... OK
  Applying sites.0002_alter_domain_unique... OK
  Applying socialaccount.0001_initial... OK
  Applying socialaccount.0002_token_max_lengths... OK
  Applying socialaccount.0003_extra_data_default_dict... OK
  ...

Если в таблицах, которые вы удалили (например, таблицы socialaccount), были данные, восстановите их из резервных таблиц:

INSERT INTO socialaccount_socialaccount
  SELECT * FROM bak1_socialaccount_socialaccount;

Это предполагает, что эти таблицы не являются частью новой миграции (например, у них точно такая же схема). Если применяется какая-либо миграция, это потребует дополнительной работы. Вероятно, это материал для другой статьи.

📢 Комментарий ниже: Вы столкнулись с этой ошибкой? Каково было ваше решение?

👉‍‍ Поделитесь этой статьей с 3 своими друзьями или коллегами. В Twitter, LinkedIn или Mastodon. Обязательно отметьте меня в публикации. Помогает мне узнать, актуален ли мой контент.

💓 Подпишитесь на DamnGoodTech на Ko-Fi всего за 7 долларов в месяц. Получайте статьи на 3 дня раньше и получайте благодарность за каждую статью! Это все равно, что нанять тимлида в вашу компанию по разработке программного обеспечения за гораздо меньшую заработную плату. 🙏🏻 Особая благодарность Джеймсу Н., Люси Р. и Стиву О. за вашу поддержку.

💼 Наймите меня в качестве руководителя технического отдела. У меня более 10 лет опыта разработки, и я хотел бы помочь вашей команде полностью раскрыть свой потенциал. Перейдите на https://damngood.tech/pages/schedule.html, чтобы назначить бесплатную консультацию.