I am adding a field to my table using alembic.
I am adding the field last_name
, and filling it with data using do_some_processing
function which loads data for the field from some other source.
This is the table model, I added the field last_name
to the model
class MyTable(db.Model):
__tablename__ = "my_table"
index = db.Column(db.Integer, primary_key=True, nullable=False)
age = db.Column(db.Integer(), default=0)
first_name = db.Column(db.String(100), nullable=False)
last_name = db.Column(db.String(100), nullable=False)
Here is my migration which works well
# migration_add_last_name_field
op.add_column('my_table', sa.Column('last_name', sa.String(length=100), nullable=True))
values = session.query(MyTable).filter(MyTable.age == 5).all()
for value in values:
first_name = value.first_name
value.last_name = do_some_processing(first_name)
session.commit()
The issue is, that using session.query(MyTable)
causes issues in future migrations.
For example, if I add in the future a migration which adds a field foo
to the table, and add the field to class MyTable
,
If I have unupdated environment, it will run migration_add_last_name_field
and it fails
sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError)
(1054, "Unknown column 'my_table.foo' in 'field list'")
[SQL: SELECT my_table.`index` AS my_table_index, my_table.first_name AS my_table_first_name,
my_table.last_name AS my_table_last_name, my_table.foo AS my_table_foo
FROM my_table
WHERE my_table.age = %s]
[parameters: (0,)]
(Background on this error at: http://sqlalche.me/e/13/e3q8)
since the migration that adds foo
runs only after, but session.query(MyTable)
takes all the fields in MyTable
model including foo
.
I am trying to do the update without selecting all fields to avoid selecting fields that were not created yet, like this:
op.add_column('my_table', sa.Column('last_name', sa.String(length=100), nullable=True))
values = session.query(MyTable.last_name, MyTable.first_name).filter(MyTable.age == 0).all()
for value in values:
first_name = value.first_name
value.last_name = do_some_processing(first_name)
session.commit()
But this results an error: can't set attribute
I also tried different variations of select *
also with no success.
What is the correct solution?