Множественные миграции Django Postgres: "Миграции не применяются"

Настройка: одна база данных Postgres с двумя схемами: "по умолчанию" и "другие". С помощью:

  • Django==2.0.10
  • psycopg2-binary==2.7.7 (нет бинарной версии в производстве)

Моя конфигурация базы данных:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'OPTIONS': {
            'options': '-c search_path=django,default',
        },
        ...
        'TEST': {
            'NAME': 'default',
            'DEPENDENCIES': ['other'],
        },
        'ATOMIC_REQUESTS': True,
    },
    'other': {
        'ENGINE': 'django.db.backends.postgresql',
        'OPTIONS': {
            'options': '-c search_path=other,default',
        },
        ...
        'TEST': {
            'NAME': 'other',
            'DEPENDENCIES': [],
        },
        'ATOMIC_REQUESTS': True,
    }
}

Шаги, сделанные на новой базе данных:

  • py manage.py migrate: работает должным образом, и схема "по умолчанию" переносится правильно.
  • py manage.py migrate --database=other результаты в: No migrations to apply.

Как ни странно, выполнение этих шагов (опять же, в новой базе данных) в обратном порядке работает:

  • py manage.py migrate --database=other: работает как положено, и "другая" схема переносится правильно.
  • py manage.py migrate Результат: работает как положено, и схема "по умолчанию" переносится правильно.

Я подозреваю, что это как-то связано с django_migrations Таблица. Я не знаю много об этой таблице, есть ли один на схему Postgres? Или есть только один django_migrations таблица на проект? После долгих поисков я увидел много предложений по использованию маршрутизаторов баз данных. "Другая" схема должна иметь все те же таблицы, что и схема "по умолчанию", поэтому маршрутизатор в этом случае не поможет.

Я пытался выполнить SQL DELETE FROM django_migrations после запуска миграций по умолчанию и затем выполнения миграций по другому; это работает только для первой миграции на новую базу данных, любые последующие попытки миграции приводят к ошибке, так как Django пытается применить уже примененные миграции и вызывает django.db.utils.ProgrammingError: relation "<relation>" already exists,

Я также пытался поиграть с django.db.migrations.recorder.MigrationRecorder класс для очистки таблицы миграции между миграцией базы данных "по умолчанию" и "другая", опять же не повезло.

Кроме того, единственный способ, которым я смог запустить свой набор тестов, состоял в том, чтобы установить "other" как зависимость для "default", чтобы использовать странный факт, что миграция "other" до "default" работает.

Я в недоумении относительно того, почему это происходит, я уверен, что что-то мне не хватает.

Обновить

Предпринимаем те же шаги, что и ранее:

  • py manage.py migrate: работает должным образом, и схема "по умолчанию" переносится правильно.
  • py manage.py migrate --database=other результаты в: No migrations to apply.

После нескольких копаний в pgAdmin я запустил следующий SQL

SET search_path TO default
SELECT * FROM django_migrations

и это вернуло таблицу прикладных миграций, как и ожидалось. Затем запустить следующий SQL

SET search_path TO other
SELECT * FROM django_migrations

и я получил сообщение о том, что отношение "django_migrations" не существует. Так что это отвечает на мой вопрос относительно django_migrations таблица: должна быть одна на схему, и это, конечно, имеет смысл.

Так что это заставляет меня думать, что Джанго, должно быть, смотрит на django_migrations таблица из схемы "по умолчанию" при попытке перенести "другую" схему и, таким образом, видит, что "миграции не применяются". Я буду продолжать пытаться решить эту проблему, любые указатели будут иметь большое значение, так как я все еще не уверен, как заставить миграции работать на обеих схемах.

Обновить

Я написал это как ответ, но это решение работало только локально, поэтому я добавил его вместо обновления.

Посмотрев на DATABASES Конфигурация на некоторое время я наконец понял, что вызывает проблемы, которые я видел. Я предоставил список через запятую для каждого search_path вариант вроде так:

DATABASES = {
    'default': {
        ...
        'OPTIONS': {
            'options': '-c search_path=django,default',
        },
        ...
    },
    'other': {
        ...
        'OPTIONS': {
            'options': '-c search_path=other,default',
        },
        ...
    }
}

Моя интерпретация происходящего здесь: при беге py manage.py migrate на свежей базе данных Django увидит, что нет django_migrations таблицы в схеме "по умолчанию", создайте ее и затем заполните, когда она применяет миграции. Затем, когда я бегу py manage.py migrate --database=other это будет выглядеть в "другом" для django_migrations, не найти его, и тогда он должен выглядеть по умолчанию, так как это следующее место для поиска в пути поиска. Как django_migrations уже существует в схеме "по умолчанию", Django будет использовать эту таблицу, а затем увидит, что "миграции не применяются". Возможно, я здесь не совсем точен, пожалуйста, поправьте меня, если я сказал что-то явно неправильное.

Изменение путей поиска в DATABASES Конфигурация вроде так:

DATABASES = {
    'default': {
        ...
        'OPTIONS': {
            'options': '-c search_path=default',
        },
        ...
    },
    'other': {
        ...
        'OPTIONS': {
            'options': '-c search_path=other',
        },
        ...
    }
}

привел к успешной миграции обеих схем в моей локальной среде. Однако это не работает, когда миграции выполняются на TravisCI или Heroku. Оба из них дают эту ошибку при миграции либо "по умолчанию", либо "другое":

Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
    return self.cursor.execute(sql)
psycopg2.ProgrammingError: no schema has been selected to create in
LINE 1: CREATE TABLE "django_migrations" ("id" serial NOT NULL PRIMA...

1 ответ

Решение

Решение моих проблем состоит из двух частей.

Получение миграции для работы на TravisCI

После обнаружения невероятной функции поиска репозитория GitHub я искал любое использование CREATE SCHEMA <schema_name> в любой .travis.yml файл.

Я изменил эти две строки в before_script из моего .travis.yml файл из

- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -U postgres

в

- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -d travisci -U postgres

Добавление -d travisci Аргумент привел к корректной миграции обеих схем.

Заставить мигрантов работать на Heroku

Я использовал эту команду для доступа к клиенту SQL для моего приложения Heroku:

heroku pg:psql -a <app_name>

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

heroku pg:psql <database_name> -a <app_name>

Также с помощью pgAdmin работало создание схемы.

Другие вопросы по тегам