【问题标题】:Flask-migrate: change model attributes and rename corresponding database columnsFlask-migrate:更改模型属性并重命名相应的数据库列
【发布时间】:2019-05-07 05:14:06
【问题描述】:

我对 Flask 有一些经验,但对数据库(Flask-migrate / 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 users 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 应用程序中的数据库列?或者换句话说,如果我想修改给定模型的属性,我必须做什么才能正确重命名数据库中的相应列名?

【问题讨论】:

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


【解决方案1】:

要简单地重命名 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 描述了同样的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 2021-09-07
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多