如何使用Flask-Migrate进行数据库迁移?

时间:2018-10-29 14:16:16

标签: flask flask-migrate

在使用Flask-Migrate升级/降级数据库时遇到问题。 UserPost这两个表由以下类定义:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    posts = db.relationship('Post', backref='author', lazy='dynamic')

    def __repr__(self):
        return '<User {}>'.format(self.username)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id')) 

我已经在这些表中添加了一些条目。

现在是问题所在。 :)

出于娱乐目的,我通过Userdummy = db.Column(db.String(20))表中添加了一个列。修改表架构后,我运行了以下命令:

  1. flask db migrate ----成功
  2. flask db upgrade ----成功

然后我想返回:

  1. 要将数据库恢复到以前的状态,我运行flask db downgrade ----失败,并显示错误:sqlite3.OperationalError: near "DROP": syntax error
  2. 我试图通过从dummy = db.Column(db.String(20))类中删除User语句来修复错误,然后再次运行flask db downgrade-再次失败,并出现相同的错误。
  3. 然后我认为Flask-Migrate可能需要注意删除操作,因此我运行了flask db migrate ----成功
  4. 尝试flask db upgrade ----再次失败,出现相同的错误。

那么长颈瓶迁移的工作原理是什么?具体来说,如何将数据库还原到初始状态(没有dummy属性)?

谢谢!

2 个答案:

答案 0 :(得分:1)

Flask迁移在运行flask db migrate命令时会生成迁移脚本。您可以查看这些迁移文件中的命令,以查看它们在做什么,并确保它们在做正确的事情。实际上,建议您在运行自动生成的迁移脚本之前先对其进行检查。

如果您更改了某些内容并且不重新运行migrate命令,那么升级和降级都不会做任何不同的事情,因为它们只是在migration文件夹中运行相应的迁移脚本。

如果数据库不重要,那么最简单的方法是删除数据库和迁移脚本,然后再次运行flask db init并重新获得有关迁移脚本的新知识,看看能否获得帮助升级和降级。

答案 1 :(得分:1)

从本质上讲,SQLite不支持删除或更改列(显然我猜您使用的是SQLite)。这意味着SQLite不支持ALTER语句,但是关系模式迁移依赖于此语句。

要解决此问题,您必须制作一系列与新结构相对应的SQLite表副本,将数据从现有表转移到新表中,然后删除旧表。

幸运的是,对于Alembic / Flask迁移,有一个上下文管理器batch_alter_table),您可以轻松管理所有这些更改。

对于您而言,解决方案是打开迁移脚本,并在downgrade()方法级别,用以下命令替换那里的指令(可能是op.drop_column('roles', 'dummy')):

with op.batch_alter_table('roles') as batch_op:
    batch_op.drop_column('dummy')

有关更多信息,请参见this link

一些小细节:

  • 在使用迁移工具时,请切记自动迁移并不总是准确的,并且会遗漏一些细节。自动生成的迁移脚本应始终进行审查。

  • 以防万一,在降级数据库时,请确保删除迁移脚本,然后生成一个新脚本来替换它。