Suppose my db model contains an object User
:
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(String(32), primary_key=True, default=...)
name = Column(Unicode(100))
and my database contains a users
table with n rows. At some point I decide to split the name
into firstname
and lastname
, and during alembic upgrade head
I would like my data to be migrated as well.
The auto-generated Alembic migration is as follows:
def upgrade():
op.add_column('users', sa.Column('lastname', sa.Unicode(length=50), nullable=True))
op.add_column('users', sa.Column('firstname', sa.Unicode(length=50), nullable=True))
# Assuming that the two new columns have been committed and exist at
# this point, I would like to iterate over all rows of the name column,
# split the string, write it into the new firstname and lastname rows,
# and once that has completed, continue to delete the name column.
op.drop_column('users', 'name')
def downgrade():
op.add_column('users', sa.Column('name', sa.Unicode(length=100), nullable=True))
# Do the reverse of the above.
op.drop_column('users', 'firstname')
op.drop_column('users', 'lastname')
There seem to be multiple and more or less hacky solutions to this problem. This one and this one both propose to use execute()
and bulk_insert()
to execute raw SQL statements during a migration. This (incomplete) solution imports the current db model but that approach is fragile when that model changes.
How do I migrate and modify the existing content of column data during an Alembic migration? What is the recommended way, and where is it documented?