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()