Hi,
First of all, thank you for these great tools making my developer's life so 
much easier and pleasant.

I need suggestion/help on how to utilize multi-tenant schemes in Alembic. I 
have few projects under the development that requires multi-tenancy in such 
way that there will be some common/shared data stored in general(public) 
schema shared by multiple schemes. In each schema there is same set of 
tables - no exception. I followed some docs and managed to find this 
<https://gist.github.com/nickretallack/bb8ca0e37829b4722dd1> one (but its 
rather old and not sure if it is still valid). Also, using some other links 
(cant recall which exactly) I managed to find a similar solution (see the 
attached env.py), but in which case, there is alembic migration version 
table in each schema. This is not big issue, but it left me with the 
feeling of incompleteness, like I am missing something important. I would 
like to use pure SqlAlchemy/Alembic *without* Flask.

Anyone has a suggestion?

Thank you all in advance

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy-alembic" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy-alembic+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
from __future__ import with_statement
from alembic import context
from sqlalchemy import engine_from_config, pool
from logging.config import fileConfig
import logging

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
# from api.database import Base
from api.model import *
from flask import current_app
config.set_main_option('sqlalchemy.url',
                       current_app.config.get('SQLALCHEMY_DATABASE_URI'))
# target_metadata = current_app.extensions['migrate'].db.metadata
target_metadata = Base.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option('sqlalchemy.url')
    context.configure(url=url)

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """

    # this callback is used to prevent an auto-migration from being generated
    # when there are no changes to the schema
    # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
    def process_revision_directives(context, revision, directives):
        if getattr(config.cmd_opts, 'autogenerate', False):
            script = directives[0]
            if script.upgrade_ops.is_empty():
                directives[:] = []
                logger.info('No changes in schema detected.')

    engine = engine_from_config(config.get_section(config.config_ini_section),
                                prefix='sqlalchemy.',
                                poolclass=pool.NullPool)

    connectable = engine.connect()
    with connectable.connect() as connection:
        for tenant_schema_name in ['serbia']:
            conn = connection.execution_options(schema_translate_map={'tenant_schema': tenant_schema_name})

            logger.info('Migrating tenant schema %s' % tenant_schema_name)

            context.configure(connection=conn,
                              target_metadata=target_metadata,
                              version_table_schema=tenant_schema_name,
                              include_schemas=True,
                              process_revision_directives=process_revision_directives,
                              **current_app.extensions['migrate'].configure_args)

            with context.begin_transaction():
                context.run_migrations()

if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

Reply via email to