Колба-перенос базы данных изменений перед обновлением

#flask-sqlalchemy #alembic #flask-migrate #flask-script

#колба-sqlalchemy #перегонный куб #колба-миграция #колба-скрипт

Вопрос:

У меня настроена структура с несколькими арендаторами, где для каждого клиента настроена схема. Структура отражает «родительскую» схему, поэтому любая миграция, которая происходит, должна происходить для каждой схемы одинаково.

Я использую Flask-Script с Flask-Migrate для обработки миграций.

То, что я пробовал до сих пор, это перебирать имена моих схем, создавать для них URI, определять область действия нового db.session с помощью движка, созданного на основе URI, и, наконец, запускать функцию обновления из flask_migrate.

     @manager.command
    def upgrade_all_clients():
        clients = clients_model.query.all()
        for c in clients:
            application.extensions["migrate"].migrate.db.session.close_all()
            application.extensions["migrate"].migrate.db.session = db.create_scoped_session(
                options={
                    "bind": create_engine(generateURIForSchema(c.subdomain)),
                    "binds": {},
                }
            )
            upgrade()
        return
  

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

Моя теория заключается в том, что я не изменяю сеанс, который был изначально настроен при запуске скрипта manager.

Есть ли лучший способ перенести каждую из этих схем без установки нескольких привязок и использования параметра —multidb ? Я не думаю, что смогу использовать SQLALCHEMY_BINDS в конфигурации, поскольку эти схемы должны иметь возможность динамически создаваться / уничтожаться.

Ответ №1:

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

 @manager.command
def upgrade_all_clients():
    clients = clients_model.query.all()
    for c in clients:
        print("Upgrading client '{}'...".format(c.subdomain))
        db.engine.url.database = c.subdomain
        _upgrade()
    return
  

Атрибут базы данных db.engine.url — это то, что предназначено для схемы. Я не знаю, лучший ли это способ решить эту проблему, но он работает, и я могу перенести каждую схему по отдельности.