Flask 如何在alembic迁移中为每行设置唯一值

Flask 如何在alembic迁移中为每行设置唯一值,flask,sqlalchemy,alembic,flask-migrate,sqlalchemy-migrate,Flask,Sqlalchemy,Alembic,Flask Migrate,Sqlalchemy Migrate,我为MyModelmodel添加了一个唯一的属性uid: class MyModel(db.Model): ... uid = db.Column(db.String(50), nullable=False) ... __table_args__ = (UniqueConstraint('uid', name='unique_uid'),) 我有一个迁移: def upgrade(): op.add_column('mymodel', sa.Column('uid',

我为
MyModel
model添加了一个唯一的属性
uid

class MyModel(db.Model):
...
    uid = db.Column(db.String(50), nullable=False)
...
    __table_args__ = (UniqueConstraint('uid', name='unique_uid'),)
我有一个迁移:

def upgrade():
    op.add_column('mymodel', sa.Column('uid', sa.String(length=50), nullable=True))

    mymodel = table('mymodel', column('uid'))
    op.execute(mymodel.update().values(uid=generate_uid()))
    op.create_unique_constraint('unique_uid', 'mymodel', ['uid'])

    op.alter_column(
        table_name='mymodel',
        column_name='uid',
        nullable=False
    )
运行时
db升级
我遇到一个错误:

...
psycopg2.IntegrityError: could not create unique index "unique_uid"
DETAIL:  Key (uid)=(c92U6txA2) is duplicated.
如何为op.execute(mymodel.update().values(uid=generate\u uid())上的每一行设置唯一值?

$ pip freeze
alembic==0.8.6
Flask==0.10.1
Flask-Fixtures==0.3.3
Flask-Login==0.3.2
Flask-Migrate==1.8.0
Flask-Script==2.0.5
Flask-SQLAlchemy==2.1
itsdangerous==0.24
Jinja2==2.8
Mako==1.0.4
MarkupSafe==0.23
psycopg2==2.6.1
python-editor==1.0
requests==2.10.0
SQLAlchemy==1.0.13
Werkzeug==0.11.9

您编写的迁移脚本将相同的uid放在所有行上,调用一次
generate\u uid()
函数,然后将其结果添加到所有行中。因此,当创建索引时,会出现重复的键错误

根据UID和数据库的不同,您可能可以编写一条SQL语句,为所有行创建唯一的ID,但安全的做法是执行循环并分别更新每一行。

可能的解决方案:

from sqlalchemy.orm import Session
from alembic import op
import sqlalchemy as sa

def upgrade():
    conn = op.get_bind()
    session = Session(bind=conn)

    op.add_column('mymodel', sa.Column('uid', sa.String(length=50), nullable=True))

    for item in session.query(MyModel).filter_by(uid=None):
        item.uid = generate_uid()
    session.commit()

    op.create_unique_constraint('unique_uid', 'mymodel', ['uid'])

    op.alter_column(
        table_name='mymodel',
        column_name='uid',
        nullable=False
    )

什么是
生成uid()
?你用的是什么数据库?我认为这不重要。但尽管如此:generate_uid()返回了唯一的值,如1Er45gh78k;DB is PostgreSQLI只希望在迁移代码中获得解决方案(如果可能的话)。如果不编写SQL代码,您可能没有意识到,但是迁移脚本中的
op.execute
行实际上正在运行SQL。如果不想写SQL,不必写SQL,如果愿意,可以使用SQLAlchemy,这不会改变答案。我已经有了一个函数,可以为uid列-generate_uid()返回唯一值。我不想把这个函数克隆到数据库中。我想在迁移中应用此函数。编写一个Python循环,每行调用一次此函数。如果我更新所有列,就会出现此错误错误错误[root]错误:所有MySQL更改/修改列操作都需要现有类型。