I am trying to migrate a SQL database using sqlAlchemy and Alembic. I would like to make simple migration scripts directly in Python code, and not by using Alembic CLI, as described in the docs.
I only found this SO question on this topic: Using Alembic API from inside application code
Using this question + Flask-Alembic source code, I tried these simple commands. engine is linked to my db & metadata contains the information for the migration.
I think I am very close, and the solution should be in one line of code... I'm struggling.
from alembic.config import Config
from alembic import command, autogenerate
from alembic.script import ScriptDirectory
from alembic.runtime.environment import EnvironmentContext
alembic_cfg = Config()
alembic_cfg.set_main_option("script_location", "migrations")
alembic_cfg.set_main_option("url", "postgresql://user:pass@postgres:5432/mydb")
alembic_script = ScriptDirectory.from_config(alembic_cfg)
alembic_env = EnvironmentContext(alembic_cfg, alembic_script)
conn = engine.connect()
alembic_env.configure(connection=conn, target_metadata=metadata)
alembic_context = alembic_env.get_context()
I am able to use the following commands to see that it works and detects what fields have to migrate :
autogenerate.compare_metadata(alembic_context, metadata)
autogenerate.produce_migrations(alembic_context, metadata)
However, I am not able to run the migrations. I tried several commands, and always get an error...
Ex, if I run:
with alembic_env.begin_transaction():
alembic_env.run_migrations()
I get :
/usr/local/lib/python2.7/site-packages/alembic/runtime/migration.pyc in run_migrations(self, **kw)
301 head_maintainer = HeadMaintainer(self, heads)
302
--> 303 for step in self._migrations_fn(heads, self):
304 with self.begin_transaction(_per_migration=True):
305 if self.as_sql and not head_maintainer.heads:
TypeError: 'NoneType' object is not callable
Could anyone help me. I think the solution is a one-liner, but I cannot find how to run the migration on my database...
For information, I have never done any migration on this DB with Alembic, maybe there is the need of an "init" ?
Thanks a lot.
for step in self._migrations_fn(heads, self):
Here we shall describe in what order you want to migrate. The sequence consists of steps, each of have step.migration_fn(**kw)
.
The last step you need is add _migrations_fn
while you do alembic_env.configure
.
def do_upgrade(revision, context):
return alembic_script._upgrade_revs(script.get_heads(), revision)
alembic_env.configure(connection=conn, target_metadata=metadata, fn=do_upgrade)
script.get_heads()
returns the last migration. Replace, if you need a specific revision, instead of the last.
Related links:
Using Alembic API from inside application code
https://bitbucket.org/davidism/flask-alembic/src/e036f063af1ba667c74560264639a93d812dfd51/flask_alembic/extension.py?at=default&fileviewer=file-view-default#extension.py-324
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With