0

私はSqlAlchemy/Flaskアプリケーションを持っています。その中には、MyModelAという名前の既存のモデルがあります。これは次のようになります。DB移行ファイルの列間でデータをコピー/移動できますか?

​​

ここでは、子モデルMyModelBを追加しています。その後、私はpython manage.py migrateを実行

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) 

:これは、次のようになります。これは、移行ファイルに表示するものである:

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の子レコードのため、それがMyModelA.my_field1からMyModelB.my_field2セットで作成する必要があることなど、この移行を編集したいです。どうしたらいいですか?

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

+0

あなたの移行スクリプト内の任意のデータベースのコードを書くことができ、基本的な制限がyを使用できないことです私たちのORMモデルではなく、SQLAlchemyコアまたはプレーンSQLを使用する必要があります。ここにいくつかの例がある記事があります:https://www.julo.ch/blog/migrating-content-with-alembic/あなたの例では、ダウングレードをアップグレードする必要はありません。 – Miguel

+0

Miguel、ありがとう。 'connection.execute()'関数を使ってレコードを挿入するにはどうしたらいいですか?そこには表示されていません。そして、あなたが今挿入したレコードの主キーをどうやって取得しますか? –

+0

SQLAlchemyのドキュメント:http://docs.sqlalchemy.org/en/latest/core/dml.html – Miguel

答えて

1

編集:

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

前の答え:あなたは本当にsqlalschemyコードたい場合の

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

あなたは1時間の移行のためにこのような何かを行うことができます。

あなたが説明していることは、通常は移行中に行うことではありません。移行は、データベースの構造を変更/作成します。あなたはそれが新しい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_b.aへの未挿入model_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() 
+0

実際に私は移行でそれをやりたがっていますが、新しい「MyModelA」が毎回それを行う必要はありません作成した。私は既に私のDBにデータを持っており、私はこの方法でそれをコピーする必要があります。 今後、私のアプリケーションは、新しいMyModelBを作成して、MyModelAの子レコードにしてデータをコピーします。 私はそれを達成するためにMiguelが提供したSQLAlchemyドキュメントの指示に従いました。ありがとう。 –

+0

入手しました。一度マイグレーションしてyesにすると、dbにModelAレコードを照会し、ModelBレコードを作成する必要があります。私の答えは、別のニーズを持つ可能性のあるGoogleの人に任せてください。 –