Python 能否在DB迁移文件中的列之间复制/移动数据?
我有一个SqlAlchemy/烧瓶应用程序。在其中,我有一个名为Python 能否在DB迁移文件中的列之间复制/移动数据?,python,sqlalchemy,flask-sqlalchemy,database-migration,flask-migrate,Python,Sqlalchemy,Flask Sqlalchemy,Database Migration,Flask Migrate,我有一个SqlAlchemy/烧瓶应用程序。在其中,我有一个名为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) class MyModelB(db.Model): b_id =
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)
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)
现在,我正在添加一个子模型MyModelB
。这就是它看起来的样子:
class MyModelA(db.Model):
a_id = db.Column(db.Integer, nullable=False, primary_key=True)
my_field1 = db.Column(db.String(1024), nullable=True)
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_field2
设置为MyModelA.my_field1
。我怎么做
请显示升级和降级代码。编辑:
对于一次性迁移,您可以执行以下操作:
db.engine.execute("INSERT INTO model_b (a_id) select a_id from model_a");
如果您确实需要sqlalschemy代码,请执行以下操作:
for model in db.query(ModelA).all()
db.session.add(ModelB(a_id=model.id))
db.session.commit()
先前的答案:
您所描述的不是迁移中通常要做的事情。迁移会更改/创建数据库的结构。如果您需要在每次创建新的MyModelA时都执行此操作,这听起来更像是事件:
此外,您的模式需要显示该关系(不仅仅是外键),以便您可以将尚未插入的模型_a分配给模型_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()
您可以在迁移脚本中编写任何数据库代码,基本限制是您不能使用ORM模型,而需要使用SQLAlchemy核心或普通SQL。下面是一篇有一些例子的文章:。在你的例子中,降级不需要改变,顺便说一下,只需要升级。米格尔,谢谢。如何使用
connection.execute()
函数记录插入?这里没有显示。那么,如何获取刚才插入的记录的主键呢?SQLAlchemy文档:实际上,我确实希望在迁移中这样做,我不需要每次创建新的MyModelA
时都这样做。我的数据库中已经有数据,我需要以这种方式复制它。接下来,我的应用程序将确保创建一个新的MyModelB
,它将是MyModelA
的子记录,并复制数据。我遵循米格尔提供的SQLAlchemy文档中的说明来实现它。谢谢,明白了。如果是一次性迁移,那么是的,您需要查询数据库中的ModelA记录并创建ModelB记录。把我的答案留给可能有不同需求的谷歌人。