I just spent a couple days getting up to speed on database migrations in general, how to make it work with Flask and Postgres and how to make them work on Heroku. There is some information out there but it took a little time hunting down what I needed; thus, I’ve summarized some of the main steps to help get others up and running with Flask, Heroku and Alembic.
Why migrate? Best practice is to avoid recreating your database(s). Usually you just want to make changes to the existing database(s) and track those changes. If at any time you need to go back to a previous version, the migration docs will help you easily revert to an old version / schema and then upgrade back to the most recent depending on your needs.
Migration Types: They are usually discussed as either schema (structure of the database) or data (the stored stuff – aka creamy filling). Sometimes they take place at the same time and sometimes not.
A Flask Migration Package Option: Alembic
Previous posts included how much I leveraged Flask Mega Tutorial for building a web application (app). In regards to migrations, Flask Mega primarily focuses on SLQLite which is not as helpful because Postgres is needed for Heroku deployment.
Alembic is a migration tool that is better maintained than the sqlalchemy-migrate package, and it is from SQLAlchemy’s author. There is documentation on how to setup and run database migrations. I’ve listed out some of the main, basic steps needed to setup alembic, migrate revisions and run it all on Heroku below. This is assuming you’ve already created a database locally as well as added it on Heroku and promoted it as the default.
Where there is a $ or => the words following should be run in the command line and yes, these directions are based on Mac.
How to Start
- Install alembic $ pip install alembic
- Add to requirements $ pip freeze > requirements.txt
- Initialize it inside your project root folder $ alembic init alembic
- Ignore the .ini file for this basic installation
- Change env.py with directions at this link. If the app is in the Flask Mega structure then just replace with app but make sure your Config file is setup for postgres:
if os.environ.get(‘DATABASE_URL’) is None:
SQLALCHEMY_DATABASE_URI = ‘postgresql://localhost/<db_name>’
SQLALCHEMY_DATABASE_URI = os.environ[‘DATABASE_URL’]
- Create first revision $ alembic revision -m “First revision.”
- Find and add change scripts for upgrade and downgrade to the new revision file
- Migrate $ alembic upgrade head
- Repeat 6 – 8 for further local revisions and migrations
- Revise Procfile:
migrate: alembic upgrade head
upgrade: alembic upgrade +1
downgrade: alembic downgrade -1
- Git add all changes $ git add .
- Git commit $ git commit -m “Procfile and running revisions>”
- Push to Heroku $ git push heroku master
- Run alembic migrate on Heroku $ heroku run alembic upgrade head
If you get something like the following then it went well:
Running `alembic upgrade head` attached to terminal… up, run.****
INFO [alembic.migration] Context impl PostgresqlImpl.
INFO [alembic.migration] Will assume transactional DDL.
INFO [alembic.migration] Running upgrade None -> *********, Create account table
INFO [alembic.migration] Running upgrade ******** -> ********* Add zoomlevel to locations.
INFO [alembic.migration] Running upgrade ******** -> *********, Test add favorite.
INFO [alembic.migration] Running upgrade ******** -> *******, Test add favorite.
To double check changes went through on Heroku, here are a couple commands:
- Launch Postgres interactive environment on Heroku $ heroku pg:psql
- Look at tables => \dt
- Look at table schema => \d <table name>
That should cover it to get started. Creating a revision file and migrating locally as well as on Heroku are steps that should be repeated for each new migration.
As always there is more info out there for nuances and complexities to migration. There is also the autogenerate functionality that can automatically define change scripts for things like a schema change, but it is limited in what it can do. Check that out in the reference documents. No matter what, I recommend always taking a look at the revision file just to make sure it will do what you need. And have fun migrating.