2016-07-21 34 views
1

ich ein einzigartiges Attribut uid für MyModel Modell einzigartigen Wert setzen hinzugefügt:wie für jede Zeile auf alembic Migration

class MyModel(db.Model): 
... 
    uid = db.Column(db.String(50), nullable=False) 
... 
    __table_args__ = (UniqueConstraint('uid', name='unique_uid'),) 

Ich habe eine Migration:

Lauf
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 
    ) 

Auf db upgrade ich habe ein Fehler:

... 
psycopg2.IntegrityError: could not create unique index "unique_uid" 
DETAIL: Key (uid)=(c92U6txA2) is duplicated. 

Wie Setzen Sie einen eindeutigen Wert für jede Zeile auf op.execute (mymodel.update(). values ​​(uid = generate_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 
+0

Was ist 'generate_uid (')? Welche Datenbank verwendest du? – RazerM

+0

Ich denke das ist nicht wichtig. Aber nichtsdestoweniger: generate_uid() hat einen eindeutigen Wert wie 1Er45gh78k zurückgegeben; DB ist PostgreSQL – Meatbot

Antwort

0

Die mögliche Lösung:

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 
    ) 
0

Die Migration Skript, das Sie die gleiche uid schrieb auf allen Zeilen legt, wird die Funktion generate_uid() einmal aufgerufen, und das Ergebnis wird dann in allen Zeilen hinzugefügt. Wenn der Index erstellt wird, erhalten Sie einen doppelten Schlüsselfehler.

Je nachdem, was Ihre UIDs sind und die Datenbank können Sie vielleicht eine einzige SQL-Anweisung schreiben, die eindeutige IDs für alle Ihre Zeilen erstellt, aber die sichere Wette wäre, eine Schleife zu machen und jede Zeile separat zu aktualisieren.

+0

Ich möchte eine Lösung nur innerhalb des Migrationscodes erhalten (wenn es möglich ist). Ohne SQL-Code zu schreiben. – Meatbot

+0

@Meatbot Sie können es nicht erkennen, aber die 'op.execute' Zeile, die Sie in Ihrem Migrationsskript haben, führt tatsächlich SQL. Sie müssen SQL nicht schreiben, wenn Sie nicht möchten, verwenden Sie SQLAlchemy, wenn Sie bevorzugen, dass die Antwort nicht ändert. – Miguel

+0

Ich habe bereits eine Funktion, die eindeutigen Wert für UID-Spalte - generate_uid() zurückgibt. Und ich möchte diese Funktion nicht in die DB klonen. Ich möchte diese Funktion in meiner Migration anwenden. – Meatbot