pythonmigrationalembicrevision

How to prevent alembic revision --autogenerate from making revision file if it has not detected any changes?


I have project where I'm using SQLAlchemy for models and I'm trying to integrate Alembic for making migrations. Everything works as expected when I change models and Alembic sees that models have changed -> it creates good migration file with command: alembic revision --autogenerate -m "model changed"

But when I have NOT changed anything in models and I use the same command:

alembic revision --autogenerate -m "should be no migration"

revision gives me 'empty' revision file like this:

"""next

Revision ID: d06d2a8fed5d
Revises: 4461d5328f57
Create Date: 2021-12-02 18:09:42.208607

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'd06d2a8fed5d'
down_revision = '4461d5328f57'
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    pass
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    pass
    # ### end Alembic commands ###

What is purpose of this file? Could I prevent creation of this 'empty file' when alembic revision --autogenerate will not see any changes? To compare when I use Django and it's internal migration when I type command:

python manage.py makemigrations

I get output something like:

No changes detected

and there is not migration file created. Is there a way to do the same with Alembic revision? Or is there other command that could check if there were changes in models and if there were then I could simply run alembic revision and upgrade?


Solution

  • Accepted answer does not answer the question. The correct answer is: Yes, you can call alembic revision --autogenerate and be sure that only if there are changes a revision file would be generated:

    As per alembic's documentation

    Implemented in Flask-Migrate (exactly in this file), it's just a change to env.py to account for the needed feature, namely to not autogenerate a revision if there are no changes to the models.

    You would still run alembic revision --autogenerate -m "should be no migration" but the change you would make to the env.py is, in short:

        def run_migrations_online():
            # almost identical to Flask-Migrate (Thanks miguel!)    
            # this callback is used to prevent an auto-migration from being generated
            # when there are no changes to the schema
        
            def process_revision_directives(context, revision, directives):
                if config.cmd_opts.autogenerate:
                    script = directives[0]
                    if script.upgrade_ops.is_empty():
                        directives[:] = []
                        print('No changes in schema detected.')
        
            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,
                    process_revision_directives=process_revision_directives
                )
        
                with context.begin_transaction():
                    context.run_migrations() 
    

    Now, you can easily call alembic revision --autogenerate without risking the creation of a new empty revision.