Deploying a Flask App with Peewee to Heroku

Background

Flask is a micro web application framework that allows rapid development and prototyping.  Having used Ruby on Rails, I wanted to try it out to see how it helps with prototyping a web app.

If you have not used Rails before, it works out of the box.  You type rails new <appname> and you get files generated in an organised directory structure – models, views, controllers, configuration files, tests, etc.  It also comes with SQLite database.  You have everything you need.  Sure, you need to spend some time learning which files go where and how to use the framework.

Flask on the other hand works with the concept of ‘one drop at a time.’  If you need something, you import it and use it.  There are no generated files or directory structures.  You start with a completely empty working directory.  It works really well when you want to take one small step at a time to develop what you have in mind because you need to learn only what is required and relevant.

Using Flask, I started off by building a very simple web API which uses a database.  To interface with a SQLite database in my local development environment, I used a database ORM called Peewee.  Later on, I wanted to make the app available outside local network so that more testing can be done from various devices.  I used Heroku, as I am already familiar with it as part of my previous Rails development.

The challenge is Heroku does not support SQLite.  It does, however, offer various other types of databases.  For Django apps, a Heroku Postgres database is automatically provisioned (the same is true for Rails apps).  For all other Python apps, a Postgres add-on must be provisioned manually.  This tutorial explains how to deploy to Heroku a Flask app which uses Peewee to connect to a database.

The source code used in this tutorial is available on GitHub at: https://github.com/swifthorseman/flask-peewee-heroku-setup.

Preliminaries

  1. Your app is already running fine locally.
  2. You have created an app on Heroku and know how to deploy it there.  If not, please follow the instructions in Getting Started with Python on Heroku.

Steps

  1. Set up Postgres on Heroku, following the instructions in Heroku Postgres.  Note that in the part where it says Connecting in Python, it tells you to install psycopg2.  It also assumes that you are using Python 2 rather than Python 3, since urlparse is a Python 2 module.  If you are using Python 3, you will need to import urllib.parse and also tell Heroku which Python runtime you are using, since the default runtime is 2.7.9.
  2. Set the database handle dynamically.  We modify the model file (tellytubbies.py) so that a correct database is selected based on the environment (e.g., on Heroku, elsewhere).  For details on setting config variables, see Configuration and Config Vars.  We set the variable HEROKU to 1 (since it is a key-value pair).  The value can be set from the command line (if you have the Heroku Toolbelt installed) or from the Heroku web interface.  You can set any key-value pair.We make use of this variable in tellytubbies.py as follows:
    db_proxy = Proxy()
    
    if 'HEROKU' in os.environ:
        import urlparse, psycopg2
        urlparse.uses_netloc.append('postgres')
        url = urlparse.urlparse(os.environ["DATABASE_URL"])
        db = PostgresqlDatabase(database=url.path[1:], user=url.username, password=url.password, host=url.hostname, port=url.port)
        db_proxy.initialize(db)
    else:
        db = SqliteDatabase('tellytubbies.db')
        db_proxy.initialize(db)
  3. We also need to manage the database connections explicitly.  It is implicitly managed when running SQLite but is required when using Postgres.  It is also a good practice to manage database connections explicitly when running a web application.We add the following in server.py.
    from flask import g
    from tellytubbies import db_proxy
    
    @app.before_request
    def before_request():
        g.db = db_proxy
        g.db.connect()
    
    @app.after_request
    def after_request(response):
        g.db.close()
        return response
  4. Deploy the app to Heroku.  Once deployed, we still need to create the database.  We do so by running: python tellytubbies.py, as we would do in a development environment.
    $ heroku login
    $ heroku run bash
    $ python tellytubbies.py
    

    We verify that the tellytubby table was created by logging into the database and listing the tables using psql:

    $ heroku pg:psql
    ---> Connecting to DATABASE_URL
    psql (9.3.5, server 9.4.4)
    WARNING: psql major version 9.3, server major version 9.4.
    Some psql features might not work.
    SSL connection (cipher: ECDHE-RSA-AES256-SHA, bits: 256)
    Type "help" for help.
    
    ::DATABASE=> \dt
                 List of relations
     Schema |    Name    | Type  |     Owner
    --------+------------+-------+----------------
     public | tellytubby | table | sgaluyzmzkklpj
    (1 row)
    ::DATABASE=> select * from tellytubby;
     id |    name     | colour
    ----+-------------+--------
      1 | Tinky Winky | Purple
      2 | Dipsy       | Green
      3 | Laa-Laa     | Yellow
      4 | Po          | Red
    (4 rows)

When you connect to the app through a URL, everything should now work!

A few concluding remarks

The general advice is that you should have the same type and version of database setup in your local environment as your production database so that there are no surprises when deploying.  In my case, I wanted to prototype my app and wanted to do it iteratively, so setting up a local Postgres database was the last thing on my mind.  Now that you have read this, perhaps it is time to go and set up a local Postgres database.

References

  1. Getting Started with Python on Heroku
  2. Heroku Postgres
  3. Postgresql config for local and heroku with peewee ORM
  4. How to use Flask/Peewee with Heroku?
  5. Dynamically defining a database