sqlalchemyfastapialembic

alembic upgrade head from within FastAPI using async sqlalchemy


I've been looking at this for a while and not having any luck. If I run "alembic upgrade head" from the command line, it works great. I would like to do that from within FastAPI so when it starts up, it upgrades the database schema. So from lots of searching, I came up with this method:

async def run_migrations():
  alembic_cfg = Config("alembic.ini")
  url = str(engine.url)
  async with engine.begin() as conn:
    await conn.run_sync(alembic_cfg.set_main_option, "sqlalchemy.url", url)
    await conn.run_sync(command.upgrade, alembic_cfg, "head")

I call it during the FastAPI lifespan startup. It gives me this error:

TypeError: Config.set_main_option() takes 3 positional arguments but 4 were given

I've also tried:

await conn.run_sync(alembic_cfg.set_main_option("sqlalchemy.url", url))

But that gives me:

TypeError: 'NoneType' object is not callable

Does run_sync not like the way I'm doing this? I'm not passing 4 arguments to set_main_option. The value of url is correct because I printed it out to make sure.

Or is there an easier/better way of doing an upgrade to head from within fastapi?

Thanks


Solution

  • Probably the issue that you try to set the sqlalchemy.url in Alembic's Config object within the run_sync function. It should work if you update the code like this:

    async def run_migrations():
        alembic_cfg = Config("alembic.ini")
        
        url = str(engine.url)
        alembic_cfg.set_main_option("sqlalchemy.url", url)
        
        async with engine.begin() as conn:
            await conn.run_sync(command.upgrade, alembic_cfg, "head")