烧瓶迁移:更改模型属性并重命名相应的数据库列

时间:2019-05-07 05:14:07

标签: python-3.x flask flask-sqlalchemy alembic flask-migrate

我对Flask有一点经验,但是对数据库却没有太多经验(Flask迁移/ alembic / SqlAlchemy)。

我正在关注this教程,并且一切正常。

我有一个这样的用户模型:

# user_model.py

from app import DB
... other imports

class User(UserMixin, DB.Model):

    __tablename__ = 'users'
    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))

然后我可以初始化数据库,进行迁移,升级等

当我想更改那个 id 属性时,问题就开始了,在Python中这不是一个很好的变量名选择。假设我想将其重命名为 user_id

现在显然数据库已经存在,并且里面有一些数据。我认为也许是通过Flask-Migrate / Alembic的某种魔术,只需修改User类即可。只需将上面的id行更改为:

user_id = DB.Column(DB.Integer, primary_key=True)

如果我这样做并运行flask db migrate,我将得到:

INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added column 'users.user_id'
INFO  [alembic.autogenerate.compare] Detected removed column 'users.id'

实际上,Alembic将其检测为被删除的列并添加了新列,我认为这很有意义。

但是,如果我运行flask db upgrade,这实际上是行不通的。我收到以下错误:

  

错误[alembic.env](sqlite3.OperationalError)无法添加NOT NULL   具有默认值NULL的列[SQL:'ALTER TABLE用户ADD COLUMN   user_id INTEGER NOT NULL']

错误非常明显。关键是我不想添加新列,而只想重命名现有列。

环顾四周,我还尝试修改script.py处理升级以使用alter_column方法:

def upgrade():
    ${upgrades if upgrades else "pass"}
    # just added this line below
    op.alter_column('users', 'id', nullable=False, new_column_name='user_id')

但是,这似乎也不起作用(我收到与上述相同的错误)。

因此,问题可以归结为一个非常简单的问题:如何使用Flask-Migrate在Flask应用程序中重命名数据库列?或者换句话说,如果我希望修改给定模型的属性,我该怎么做才能正确重命名数据库中的相应列名?

1 个答案:

答案 0 :(得分:0)

仅在alembic脚本中重命名一列(与flask-migrate相同),您所做的就是正确的:

op.alter_column('users', 'id', nullable=False, new_column_name='user_id')

我认为问题来自于您还需要更改其约束作为主键:

op.drop_constraint('user_pkey', 'users', type_='primarykey')
op.create_primary_key('user_pkey', 'users', ['user_id'])

您可能需要根据数据库类型来调整重新创建的主键的名称(对于我来说,它在PostgreSQL中如此工作)

应该始终检查自动生成的Alembic脚本,如果不是为了简单的更改,往往会不执行我们想要的操作。

注意:如果您将列id用作外键,则可能还需要更改其他表中的外键约束。

Alter Primary Key in Alembic描述了相同类型的问题。