Search code examples
pythonsqlalchemyalembic

Flask-migrate (alembic) only detects changes in public schema


I have multiple schemas in my database, and several models per schema. Flask-migrate (which is Alembic) is unable to detect changes in any schema besides the public schema. Running

flask db migrate

followed by

flask db upgrade

will yield an error every time because the tables are already created. How can I configure alembic to recognize other schemas besides the public schema?


Solution

  • Modify your env.py file created by Alembic so that the context.configure function is called using the include_schemas=True option. Ensure that this is done in both your offline and online functions.

    Here are my modified run_migrations_offline and run_migrations_online functions.

    
    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, target_metadata=get_metadata(), literal_binds=True, include_schemas=True
        )
    
        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.')
    
        connectable = get_engine()
    
        with connectable.connect() as connection:
            context.configure(
                connection=connection,
                target_metadata=get_metadata(),
                process_revision_directives=process_revision_directives,
                **current_app.extensions['migrate'].configure_args,
                include_schemas=True
            )
    
            with context.begin_transaction():
                context.run_migrations()