Auto Generating Migrations

自动生成迁移

Alembic can view the status of the database and compare against the table metadata in the application, generating the “obvious” migrations based on a comparison. This is achieved using the --autogenerate option to the alembic revision command, which places so-called candidate migrations into our new migrations file. We review and modify these by hand as needed, then proceed normally.

Alembic 可以查看数据库的状态并与应用程序中的表元数据进行比较,根据比较生成“显而易见”的迁移。 这是通过使用 alembic revision 命令的 --autogenerate 选项来实现的,它将所有的待迁移放入我们的新迁移文件中。 我们根据需要手动审查和修改这些,然后正常进行。

To use autogenerate, we first need to modify our env.py so that it gets access to a table metadata object that contains the target. Suppose our application has a declarative base in myapp.mymodel. This base contains a MetaData object which contains Table objects defining our database. We make sure this is loaded in env.py and then passed to EnvironmentContext.configure() via the target_metadata argument. The env.py sample script used in the generic template already has a variable declaration near the top for our convenience, where we replace None with our MetaData. Starting with:

要使用自动生成,我们首先需要修改我们的 env.py 以便它可以访问包含目标的表元数据对象。 假设我们的应用程序在 myapp.mymodel 中有一个 declarative base。 该 base 包含一个 MetaData 对象,该对象包含我们定义的数据库的 Table 对象。 我们确保它被加载到 env.py 中,然后通过 target_metadata 参数传递给 EnvironmentContext.configure()。 为方便起见,通用模板中使用的 env.py 示例脚本在靠近顶部的地方已经有一个变量声明,我们用 MetaData 替换了 None。 比如:

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = None

we change to:

我们改变成:

from myapp.mymodel import Base
target_metadata = Base.metadata
  • Note: The above example refers to the generic alembic env.py template, e.g. the one created by default when calling upon alembic init, and not the special-use templates such as multidb. Please consult the source code and comments within the env.py script directly for specific guidance on where and how the autogenerate metadata is established.

  • 注意: 上面的例子指的是“通用的 alembic env.py 模板”,例如 调用alembic init时默认创建的那个,而不是像multidb这样的特殊模板。 请直接查阅“env.py”脚本中的源代码和注释,以获取有关在何处以及如何建立自动生成元数据的具体指导。

If we look later in the script, down in run_migrations_online(), we can see the directive passed to EnvironmentContext.configure():

如果我们稍后查看脚本,在 run_migrations_online() 中,我们可以看到传递给 EnvironmentContext.configure() 的指令:

def run_migrations_online():
    engine = engine_from_config(
                config.get_section(config.config_ini_section), prefix='sqlalchemy.')

    with engine.connect() as connection:
        context.configure(
                    connection=connection,
                    target_metadata=target_metadata
                    )

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

We can then use the alembic revision command in conjunction with the --autogenerate option. Suppose our MetaData contained a definition for the account table, and the database did not. We’d get output like:

然后我们可以将alembic revision 命令与--autogenerate 选项结合使用。 假设我们的 MetaData 包含对 account 表的定义,而数据库没有。 我们会得到如下输出:

$ alembic revision --autogenerate -m "Added account table"
INFO [alembic.context] Detected added table 'account'
Generating /path/to/foo/alembic/versions/27c6a30d7c24.py...done

We can then view our file 27c6a30d7c24.py and see that a rudimentary migration is already present:

然后我们可以查看我们的 27c6a30d7c24.py 文件, 并看到一个基本的迁移已经存在:

"""empty message

Revision ID: 27c6a30d7c24
Revises: None
Create Date: 2011-11-08 11:40:27.089406

"""

# revision identifiers, used by Alembic.
revision = '27c6a30d7c24'
down_revision = None

from alembic import op
import sqlalchemy as sa

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
    'account',
    sa.Column('id', sa.Integer()),
    sa.Column('name', sa.String(length=50), nullable=False),
    sa.Column('description', sa.VARCHAR(200)),
    sa.Column('last_transaction_date', sa.DateTime()),
    sa.PrimaryKeyConstraint('id')
    )
    ### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table("account")
    ### end Alembic commands ###

The migration hasn’t actually run yet, of course. We do that via the usual upgrade command. We should also go into our migration file and alter it as needed, including adjustments to the directives as well as the addition of other directives which these may be dependent on - specifically data changes in between creates/alters/drops.

当然,迁移还没有真正运行。 我们通过常用的upgrade命令来做到这一点。 我们还应该进入我们的迁移文件并根据需要更改它,包括对指令的调整以及添加这些可能依赖的其他指令 - 特别是在创建/更改/删除之间的数据更改。