5

SqlAlchemy/Flask アプリケーションがあります。その中に、 という名前の既存のモデルがありMyModelAます。これは次のようになります。

class MyModelA(db.Model):
    a_id   = db.Column(db.Integer, nullable=False, primary_key=True)
    my_field1 = db.Column(db.String(1024), nullable=True)

今、子モデルを追加していMyModelBます。これは次のようになります。

class MyModelB(db.Model):
    b_id   = db.Column(db.Integer, nullable=False, primary_key=True)
    a_id = db.Column(db.Integer, db.ForeignKey(MyModelA.a_id), nullable=False)
    my_field2 = db.Column(db.String(1024), nullable=True)

それから私は走りpython manage.py migrateます。これは、移行ファイルに表示されるものです。

def upgrade():
    op.create_table('my_model_b',
    sa.Column('b_id', sa.Integer(), nullable=False),
    sa.Column('a_id', sa.Integer(), nullable=False),
    sa.Column('my_field2', sa.String(length=1024), nullable=True),
    sa.ForeignKeyConstraint(['a_id'], [u'my_model_a.a_id'], ),
    sa.PrimaryKeyConstraint('b_id')
    )

def downgrade():
    op.drop_table('my_table_b')

MyModelAのすべてのインスタンスに対して、インスタンスの子レコードをに設定してMyModelB作成する必要があるように、この移行を編集したいと考えています。どうすればいいですか?MyModelB.my_field2MyModelA.my_field1

アップグレードとダウングレードのコードを表示してください。

4

1 に答える 1

2

編集:

1 回限りの移行では、次のようなことができます。

db.engine.execute("INSERT INTO model_b (a_id) select a_id from model_a");

本当に sqlalchemy コードが必要な場合:

for model in db.query(ModelA).all()
    db.session.add(ModelB(a_id=model.id))
db.session.commit()

以前の回答:

あなたが説明していることは、移行で通常行うことではありません。移行により、データベースの構造が変更/作成されます。新しい MyModelA が作成されるたびに発生する必要がある場合、これはイベントのように聞こえます: http://docs.sqlalchemy.org/en/latest/orm/events.html#session-events

class MyModelA(db.Model):
    ...


@sqlalchemy.event.listens_for(SignallingSession, 'before_flush')
def insert_model_b(session, transaction, instances):
    for instance in session.new:
        if isinstance(instance, MyModelA):
            model_b = MyModelB(a=instance)
            session.add(model_b)

また、まだ挿入されていない model_a を model_b.a に割り当てることができるように、スキーマはその関係 (外部キーだけでなく) を示す必要があります。

class MyModelB(db.Model):
    b_id   = db.Column(db.Integer, nullable=False, primary_key=True)
    a_id = db.Column(db.Integer, db.ForeignKey(MyModelA.a_id), nullable=False)
    a = relationship("MyModelA")
    my_field2 = db.Column(db.String(1024), nullable=True)

完全なコード例:

import sqlalchemy
from sqlalchemy.orm import relationship
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.sqlalchemy import SignallingSession

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True

db = SQLAlchemy(app)

class MyModelA(db.Model):
    __tablename__ = 'model_a'
    a_id = db.Column(db.Integer, nullable=False, primary_key=True)
    my_field1 = db.Column(db.String(1024), nullable=True)

class MyModelB(db.Model):
    __tablename__ = 'model_b'

    b_id = db.Column(db.Integer, nullable=False, primary_key=True)
    a_id = db.Column(db.Integer, db.ForeignKey(MyModelA.a_id), nullable=False)
    a = relationship(MyModelA)
    my_field2 = db.Column(db.String(1024), nullable=True)


@sqlalchemy.event.listens_for(SignallingSession, 'before_flush')
def insert_model_b(session, transaction, instances):
    for instance in session.new:
        if isinstance(instance, MyModelA):
            model_b = MyModelB(a=instance)
            session.add(model_b)

db.create_all()
model_a = MyModelA()
db.session.add(model_a)
db.session.commit()
于 2016-11-16T20:10:53.523 に答える