Introduction Pricing and Billing FAQ Account FAQ Technical FAQ Tutorials Contact Us

Setting Up Flask, SQLAlchemy, and Postgres

This tutorial explains how to configure Flask and Postgres to work together. We will learn by walking through a simple Pastebin clone in Python and Flask, connecting it to a Database Labs Postgres database using SQLAlchemy.

Database Labs reduces the formerly difficult task of setting up a continuously backed-up database in the cloud to one command, greatly reducing the development time.

Prerequisites

You should have a basic knowledge of general Python programming and source code editing, and be comfortable running commands at the command line. Make sure you have a recent version of Python and its package tool, pip, installed on your system. Consult the Hitchhiker's Guide to Python if you need general help with Python.

We'll use the psql Postgres client to interact with the Database Labs database. On Debian and Ubuntu Linux systems, this is in a package called postgresql-client. You can also use pgAdmin as your Postgres client.

If you don't have it installed already, please install HTTPie, a command-line HTTP client similar to curl. We'll use it to make the API request to Database Labs.

Step 1: Get a Database Labs API Key

After logging in and setting up payment details, click on the API Keys tab, then click the Create API Key button. Copy down your API key details somewhere safe.

To make things easier, we'll save the API key and the API secret into the following environment variables:

export DBLABS_API_KEY=<API key goes here>
export DBLABS_API_SECRET=<API secret goes here>
export DBLABS_API_LOGIN=$DBLABS_API_KEY:$DBLABS_API_SECRET

Step 2: Provision a Database

Creating a new database with the API is easy:

$ http -a $DBLABS_API_LOGIN POST https://www.databaselabs.io/api/databases size=512mb

You should receive a reply like the following (with a different hostname and password, of course):

HTTP/1.1 202 Accepted
Connection: keep-alive
Content-Length: 145
Content-Type: application/json
Date: Sat, 15 Nov 2014 01:24:24 GMT
Server: nginx/1.6.2

{
    "hostname": "deep-base-73.db.databaselabs.io",
    "id": "40693e7e-8126-46bb-a10e-8c309776e5d8",
    "password": "fMdGn7beP98S2wKYFg",
    "status": "building"
}
      

It will take about 5 minutes for the database to build. You can check whether it's ready yet with the GET call. Substitute your database hostname into the following command:

$ http -a $DBLABS_API_LOGIN GET https://www.databaselabs.io/api/databases/deep-base-73.db.databaselabs.io

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 229
Content-Type: application/json;charset=UTF-8
Date: Sat, 15 Nov 2014 01:30:07 GMT
Server: nginx/1.6.2
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Accept

{
    "hostname": "deep-base-73.db.databaselabs.io",
    "hostsize": "512mb",
    "id": "40693e7e-8126-46bb-a10e-8c309776e5d8",
    "region": "nyc3",
    "sla": "development",
    "status": "ready",
    "updated-at": "2014-11-15T01:29:59.041Z",
    "cloud": "digitalocean"
}

Great! The "status: ready" tells us that our database is good to go. Let's start with the Python setup.

Step 3: Install Python packages

Our project is going to be based in a Python virtual environment called venv. A virtual environment is just a way to group together all the various packages used by our project. We are going to need the Flask, psycopg2 and Flask-SQLAlchemy packages.

We set up our virtual environment with:

$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip...done.
$ source venv/bin/activate
(venv)$ pip install Flask Flask-SQLAlchemy psycopg2
...
(venv)$

Step 4: Set up the database model

Open main.py in your favorite editor and add the following:

# main.py

from flask import *
from flask.ext.sqlalchemy import SQLAlchemy

import os, sys

app = Flask(__name__)
app.config.from_object(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL")
if app.config['SQLALCHEMY_DATABASE_URI'] == None:
    print "Need database config"
    sys.exit(1)

db = SQLAlchemy(app)

import models

if __name__ == "__main__":
    app.run(host='0.0.0.0')

A database model is the class representing a row in the database. Ours is going to be very simple:

# models.py

from main import app, db
import uuid

class Paste(db.Model):
    id = db.Column(db.String(36), unique=True, primary_key=True)
    poster = db.Column(db.String(51))
    paste = db.Column(db.Text())

    def __init__(self, text, poster="Anonymous"):
        self.paste = text
        self.id = str(uuid.uuid4())

Step 5: Set up the HTML views

Our 3 HTML templates are going to also be very simple:

<!-- templates/paste.html -->
<h1>Paste</h1>

<code>
{{ paste }}
</code>
<!-- templates/submit.html -->
<h1>Paste</h1>
<h4>Add a Paste</h4>
<form action="/submit" method=post>
	<dl>
		<dt>Paste:
		<dd><textarea type=text name=paste rows="20" cols="80"></textarea>
		<br />
		<input type=submit value=Submit>
	</dl>
</form>
<!-- templates/success.html -->
<h2>Success!</h2>

<p>You can find your paste at <a href="/{{id}}">this URL</a>.

Step 6: Set up form processing

For simplicity, / is going to be the submit page.

# main.py

@app.route("/")
def show_submit_page():
    return render_template("submit.html")

@app.route("/submit", methods=["POST"])
def submit():
    text = request.form["paste"]
    text = text.encode("ascii", errors="ignore")

    paste = Paste(text, "Anonymous")

    db.session.add(paste)
    db.session.commit()

    print "added paste by %s with id %s" % (poster, paste.id)
    return render_template("success.html", id=paste.id)

@app.route("/")
def show(id):
    pastes = models.Paste.query.filter_by(id=id)
    paste = pastes.first()

    if paste == None:
        raise Exception("No such paste by id %s" % id)

    return render_template("paste.html", paste=paste)

Step 7: Set the database up

Now that all the code is written, let's set up the database. Substitute your hostname and password in the following command:


$ PGPASSWORD=fMdGn7beP98S2wKYFg psql -h deep-base-73.db.databaselabs.io -U postgres
postgres=# CREATE DATABASE pastes;
CREATE DATABASE
postgres=# CREATE USER flaskapp WITH PASSWORD 's3kr1+';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE pastes TO flaskapp;
GRANT
postgres=# \q

initdb.py will create the actual database table from our model:


# initdb.py

from main import db
db.create_all()

Step 8: Run the app

Finally, we can run our app:


$ export DATABASE_URL=postgresql://flaskapp:s3kr1+@deep-base-73.db.databaselabs.io/pastes
$ python initdb.py
$ python main.py
 * Running on http://0.0.0.0:5000/

Here are some screenshots of the app in action:

That's how easily you can get started with Python on Database Labs!