This template is suitable for setting up a Heroku application that runs Python applications using Anaconda Python, with the lightweight Flask web framework, and the Alembic/Flask-Migrate database migration manager.
Applications built from this template assume Heroku-Postgres as the database backend (see below).
The application as represented here assumes that we set up both staging
and production
versions of the application on Heroku, and the instructions below reflect this. For
purposes of illustration, the base application name used here will be mmadsen-test
, but
you should choose a unique application name.
The minimal example chosen to get a Flask, postgres, and Alembic application working on
the Anaconda buildpack with Python 3.5 is RealPython's "Flask by Example" application. I like their approach to the Config
class and how that encapsulates all the
variables needed for dev, staging, and production environments.
Obviously, in replacing the content here with your own application, you may want to remove the nltk_data
directory if you're
not using the NLTK tokenizer anymore, and of course you'll need to edit the web.py
, models.py
, and everything in the templates
directory for your own purposes. But this is a good, working starting point for a minimal web-database app.
Fork this repository (or clone it and establish a new Git versioning
database using rm -rf .git; git init
). Rename the directory
to something suitable for your application.
- Copy the env-template to .env
- Copy slugignore-template to .slugignore
- Put the environment variables for configuration into your current session:
source .env
(or whatever is appropriate for your shell) - Log into Heroku using
heroku login
- Create staging and production applications on Heroku:
heroku create --buildpack https://github.com/mmadsen/conda-buildpack mmadsen-test-staging
heroku create --buildpack https://github.com/mmadsen/conda-buildpack mmadsen-test-prod
- Add Git "remotes" so that you can push this repository to each of the Heroku applications:
git remote add staging git@heroku.com:mmadsen-test-staging.git
git remote add staging git@heroku.com:mmadsen-test-prod.git
- You may wish to clean up the remotes which ship with the template by simply editing
.git/config
and removing remote blocks which no longer apply (DO THIS CAREFULLY!) - Ensure that you still have an
origin
remote (e.g., your Github fork) for storing the canonical source code for your application.
- Test that you can push the repository to each Heroku application:
git push staging master
git push prod master
If this succeeds, even if we don't have everything wired up yet, then you have one source code repository which is wired via Git to two Heroku applications, one for staging and one for production use.
The first thing to do is make sure that your local developer box has Postgres installed, along with any client tools. You can find instructions, downloads, etc at the Postgresql website. On OSX, I strongly recommend Homebrew package management for this.
For the template, the database name I'm using is "wordcount_dev" simply because I was working with a common statistics example. You should take this opportunity to rename the database to suit your application needs now, before you run any further commands.
- To create the local database:
psql -c 'create database wordcount_dev;'
- If you change the database name, change the configuration variable
DATABASE_URL
in .env and executesource .env
- Create Heroku-Postgres database add-ons for both production and staging applications. At this point, you may want to choose different sizes; for illustration purposes here I use the free hobby-dev tier.
heroku addons:create heroku-postgresql:hobby-dev --app mmadsen-test-staging
heroku addons:create heroku-postgresql:hobby-dev --app mmadsen-test-prod
- Set configuration variables on the staging and production applications, to allow them to pick up the correct information from
config.py
for their environment type:heroku config:set APP_SETTINGS=config.StagingConfig --remote staging
heroku config:set APP_SETTINGS=config.ProductionConfig --remote prod
- Verify that you have correct configurations and new database URLs for each:
heroku config --remote prod
heroku config --remote staging
Rather than managing database schemas manually, this template app employs Alembic, a python library which manages DDL migrations for SQLAlchemy. When using Flask as the web framework, we then layer Flask-Migrate on top of Alembic, to create a simple system for migrations which operates almost exactly like the Rails ActiveRecord system.
To set this up, first note that the module models.py
contains our actual schema classes. Additional modules can be imported
by simply including them in the main web.py
application module. Each table is represented by a class, in SQLAlchemy syntax.
When these classes are modified (or new ones added), Alembic notes the change and automatically constructs a "migration" to change the database structure to match. Flask-Migrate and Alembic keep these version-controlled in a directory called migrations
.
To set up the migrations
folder, you simply call python manage.py db init
. You do not need to do this given the existing
migrations in the template app, but it is necessary if you write an app structure from scratch or add Flask-Migrate to an existing application.
Once the DDL model classes have been modified, you apply them to the local database as follows:
python manage.py db migrate
-- this creates the next migration file. You may want to edit this manually before proceeding.python manage.py db upgrade
-- this applies the latest migration.
To apply the migrations to Heroku applications, in production and staging:
- Check in the changes to version control.
- Push the changes to both staging and production:
git push staging master
orgit push prod master
- Use
heroku run
to execute the migration on the remote applications, just as you did on the local database. - NOTE: Make sure you have the configuration variables for
APP_SETTINGS
set on the remote applications, so it can pick up the proper database URL.heroku run python manage.py db upgrade --app mmadsen-test-staging
heroku run python manage.py db upgrade --app mmadsen-test-prod
Further operations are possible with Flask-Migrate
as well. To downgrade schemas, use python manage.py db downgrade
for example. You can also get migration history with python manage.py db history
.