我对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应用程序中重命名数据库列?或者换句话说,如果我希望修改给定模型的属性,我该怎么做才能正确重命名数据库中的相应列名?
答案 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描述了相同类型的问题。