Yaakov Bressler
Yaakov Bressler

Reputation: 12018

Alembic ignore specific tables

I'm using alembic to manage database migrations as per user defined sqlalchemy models. My challenge is that I'd like for alembic to ignore any creation, deletion, or changes to a specific set of tables.

Note: My Q is similar to this question Ignoring a model when using alembic autogenerate but is different in that I want to control alembic from outside the model definition.

Here's a sample table I want to ignore:

from sqlalchemy import MetaData
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base(metadata=MetaData())

class Ignore1(Base):
    """
    Signed in to the account...
    """
    __tablename__ = 'ignore_1'
    __table_args__ = {
        'info':{'skip_autogenerate':True}
        }
    id = Column(Integer, primary_key=True)
    foo = Column(String(20), nullable=True)

Example code (which does not solve my issue):
In alembic/env.py

# Ideally this is stored in my actual database, but for now, let's assume we have a list...
IGNORE_TABLES = ['ignore_1', 'ignore_2']

def include_object(object, name, type_, reflected, compare_to):
    """
    Should you include this table or not?
    """

    if type_ == 'table' and (name in IGNORE_TABLES or object.info.get("skip_autogenerate", False)):
        return False

    elif type_ == "column" and object.info.get("skip_autogenerate", False):
        return False

    return True

# Then add to config
context.configure(
    ...
    include_object=include_object,
    ...
    )

Upvotes: 24

Views: 10133

Answers (1)

Yaakov Bressler
Yaakov Bressler

Reputation: 12018

I found a solution to my problem!

My error was in the instantiation of my context object in env.py

def run_migrations_offline():
    ...
    context.configure(
        url=url,
        target_metadata=target_metadata,
        include_object=include_object,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

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

I wasn't applying this change to context for online migrations:

def run_migrations_online():
    ...
    connectable = engine_from_config(
        config.get_section(config.config_ini_section),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection,
            target_metadata=target_metadata,
            # THE FOLLOWING LINE WAS MISSING FROM MY ORIGINAL CODE
            include_object=include_object, # <----------------------- THIS!
        )
    ...

Hopefully anyone else encountering this issue and experiencing similar turmoil can read through my question & following solution and recognize that despair is but a small dumb tweak from salvation.

Upvotes: 23

Related Questions