Question

I'm trying to run a fairly simple Flask + SQLAlchemy site on Heroku, but I'm not sure how I should run my migrations to set up my DB. When I run heroku run alembic upgrade head, I get the following error:

Running `alembic upgrade head` attached to terminal... up, run.1
Traceback (most recent call last):
  File "/app/.heroku/venv/bin/alembic", line 12, in <module>
    load_entry_point('alembic==0.4.0', 'console_scripts', 'alembic')()
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/config.py", line 255, in main
    CommandLine(prog=prog).main(argv=argv)
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/config.py", line 250, in main
    self.run_cmd(cfg, options)
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/config.py", line 241, in run_cmd
    **dict((k, getattr(options, k)) for k in kwarg)
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/command.py", line 124, in upgrade
    script.run_env()
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/script.py", line 191, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/app/.heroku/venv/lib/python2.7/site-packages/alembic/util.py", line 185, in load_python_file
    module = imp.load_source(module_id, path, open(path, 'rb'))
  File "alembic/env.py", line 80, in <module>
    run_migrations_online()
  File "alembic/env.py", line 63, in run_migrations_online
    poolclass=pool.NullPool)
  File "/app/.heroku/venv/lib/python2.7/site-packages/sqlalchemy/engine/__init__.py", line 349, in engine_from_config
    return create_engine(url, **opts)
  File "/app/.heroku/venv/lib/python2.7/site-packages/sqlalchemy/engine/__init__.py", line 330, in create_engine
    return strategy.create(*args, **kwargs)
  File "/app/.heroku/venv/lib/python2.7/site-packages/sqlalchemy/engine/strategies.py", line 64, in create
    dbapi = dialect_cls.dbapi(**dbapi_args)
  File "/app/.heroku/venv/lib/python2.7/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py", line 289, in dbapi

To me, this seems to indicate it's trying to load sqlite stuff (which is the default I have in alembic.ini), but I have the following in my env.py in an effort to make it use the Heroku PostgreSQL connection:

cur_db_uri = config.get_section_option('alembic', 'sqlalchemy.url')
my_db_uri = app.config.get('SQLALCHEMY_DATABASE_URI', cur_db_uri)
config.set_section_option('alembic', 'sqlalchemy.url', my_db_uri)

where app is a Flask instance. I'm using Flask-SQLAlchemy to DRY up my DB usage in the app, and Flask-Heroku to make sure all my Flask configuration variables are being pulled properly from the Heroku environment variables.

Was it helpful?

Solution

It turns out that Flask-Heroku is pulling the value of DATABASE_URL, which doesn't exist for my app on Heroku. If instead, I manually map the value of HEROKU_POSTGRESQL_CRIMSON_URL into app.config['SQLALCHEMY_DATABASE_URI'], it works as expected.

UPDATE: And it turns out that I forgot to pg:promote my DB so as to have a default for that app, which is why DATABASE_URL is non-existent. So the real solution is: don't forget to promote your DB.

UPDATE 2: Let me sum up: use flask-heroku to inject the proper SQLALCHEMY_DATABASE_URI into your app's config, tweak env.py to use your app's configured SQLALCHEMY_DATABASE_URI instead of the URL in alembic.ini, and then run alembic on Heroku's servers via heroku run alembic upgrade head (or whatever migration you want to run). This will prevent you from having to tweak the ini file to adjust for different environments (because the hosting environments will manage it for you).

OTHER TIPS

You can specify a release phase task in your Procfile. Mine ended up looking like:

web: gunicorn ...
release: alembic upgrade head

I too thought that I had to manually run alembic upgrade head on heroku for database changes to take place, but that is not the case. If you have the correct DATABASE_URL values in your application then alembic migrate is run on deploy and there is no need to run this again.

To confirm, you can connect to your database heroku pg:psql <database name> --app <application name> and check.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top