Flask-migrate 和更改列类型

Flask-migrate and changing column type

我正在尝试学习一些 Flask,我正在使用 Flask-Migrate 1.6.0

所以我做了一个看起来像这样的模型

class Download(db.Model):

    __tablename__ = "downloads"

    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    filename = db.Column(db.String, nullable=False)
    size = db.Column(db.Integer, nullable=False)
    location = db.Column(db.String, nullable=False)
    season = db.Column(db.Integer, nullable=False)
    download_timestamp = db.Column(db.DateTime, nullable=False)

    show_id = db.Column(db.Integer, ForeignKey("shows.id"))

    def __init__(self,filename,size,location,timestamp,season):
        self.filename = filename
        self.size = size
        self.location = location
        self.download_timestamp = timestamp
        self.season = season

    def __repr__(self):
        return '<File {}'.format(self.filename)

然后我将其更改为完全相同的内容,除了这一行:

size = db.Column(db.BigInteger, nullable=False)

当我 运行 我的

manager.py db migrate

command 它没有检测到列类型的变化。我已经阅读了它,我知道当我更改我的 env.py 并添加 compare_type=True 变量时它应该选择它。但是我这样做没有用,现在的方法是这样的

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.readthedocs.org/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)

    connection = engine.connect()
    context.configure(connection=connection,
                      target_metadata=target_metadata,
                      compare_type=True,
                      process_revision_directives=process_revision_directives,
                      **current_app.extensions['migrate'].configure_args)

    try:
        with context.begin_transaction():
            context.run_migrations()
    finally:
        connection.close()

好的,我的问题是:

我是不是在更改 env.py 文件时做错了什么?

如果我没有,但它仍然没有接受,我该如何手动进行下一次迁移修订?因为我的 migrate 文件夹中的修订具有如下名称和其中的内容

# revision identifiers, used by Alembic.
revision = '7e9f264b0f'
down_revision = '2e59d536f50'

我想我可以复制一个,编一个名字..但是下一个被flask migrate拾取的会识别它吗?所以是的.. 没有太多不确定的黑客攻击的正确处理方法是什么?

大多数时候 flask-migrate 没有检测到 Column 的变化。如果删除 size 字段,则 flask-migrate 将检测到更改。然后 运行

manager.py db migrate

然后添加size 归档

size = db.Column(db.BigInteger, nullable=False) 并迁移。

更新:

不出所料,此答案现已过时,请参阅 以获得真正的修复!

原答案:

默认情况下,Alembic 在自动生成修订时无法识别列类型更改等内容。在进行这些更精细的更改时,您将需要手动修改迁移以包含这些更改

例如,在您的迁移文件中

from alembic import op
import sqlalchemy as sa
def upgrade():
    # ...
    op.alter_column('downloads', 'size', existing_type=sa.Integer(), type_=sa.BigInteger())
def downgrade():
    # ...
    op.alter_column('downloads', 'size', existing_type=sa.BigInteger(), type_=sa.Integer())

具体操作见the operation reference

您可以通过修改 env.py 和 alembic.ini 来启用类型更改检测,如 here

所示

默认情况下,Flask-migrate 不会跟踪更改列类型时的更改。实现这一目标的众多方法之一是设置

compare_type=True

env.py下。例如-

context.configure(connection=connection,
                      target_metadata=target_metadata,
                      process_revision_directives=process_revision_directives,
                      compare_type=True,
                      **current_app.extensions['migrate'].configure_args)

只需要在Migrate构造函数中添加compare_type=True

from flask_migrate import Migrate
migrate = Migrate(compare_type=True)

app = Flask(__name__)
migrate.init_app(app)

我已经创建了一个脚本,用于在 Flask 中自动添加 compare_type=true,请随意使用和改进它。

make dbinit
sudo sed -i '75i\                      compare_type=True,' env.py
make dbmigrate
make dbupgadre

干杯,