Monthly Archives: February 2014

Flask Todo app with SQLAlchemy on OpenShift

Starting from the Hello World application

In this post, we will create a Todo application based on Flask and SQLAlchemy and also immediately deploy it to Openshift. We begin by creating a simple Hello World app on Openshift to ensure everything works as expected.

Flask_Todo_SQLAlchemy$ rhc app create todo python-2.7 postgresql-9.2
-------------------
Domain:     wymedia
Cartridges: python-2.7, postgresql-9.2
Gear Size:  default
Scaling:    no

Creating application 'todo' ... done

  PostgreSQL 9.2 database added.  Please make note of these credentials:

   Root User: admin4e5qzkf
   Root Password: XrT1ESN7wGzb
   Database Name: todo

Connection URL: postgresql://$OPENSHIFT_POSTGRESQL_DB_HOST:$OPENSHIFT_POSTGRESQL_DB_PORT

Waiting for your DNS name to be available ... done

Cloning into 'todo'...
Warning: Permanently added the RSA host key for IP address '54.211.168.84' to the list of known hosts.

Your application 'todo' is now available.

  URL:        http://todo-wymedia.rhcloud.com/
  SSH to:     53fb34bc5973ca33db00042b@todo-wymedia.rhcloud.com
  Git remote: ssh://53fb34bc5973ca33db00042b@todo-wymedia.rhcloud.com/~/git/todo.git/
  Cloned to:  Flask_Todo_SQLAlchemy/todo
Flask_Todo_SQLAlchemy/todo$ ls
requirements.txt  setup.py  wsgi.py
Flask_Todo_SQLAlchemy/todo$ git remote add upstream -m master git://github.com/openshift/flask-example.git
Flask_Todo_SQLAlchemy/todo$ git pull -s recursive -X theirs upstream master
Flask_Todo_SQLAlchemy/todo$ ls
data  libs  README  README.md  requirements.txt  setup.py  wsgi  wsgi.py
Flask_Todo_SQLAlchemy/todo$ git push

Visiting the http://todo-wymedia.rhcloud.com will show you the Hello World text. So far, we learned nothing new. In fact, we just redid what we explained in this post.

Creating the todo application

We will then make a bit of changes as we don’t want to have the default Hello World Flask app (pulled down from Github) but we want to create a TodoApp.

  • In application (under wsgi), change from “myflaskapp import app as application” to “from todoapp import app as application”
  • In WSGI folder, rename “myflaskapp.py” to “todoapp.py”
  • Add Flask Alchemy to the setup.py file so it looks like “install_requires=[‘Flask>=0.7.2’, ‘MarkupSafe’, ‘Flask-SQLAlchemy==0.16’]”

When you have finished making these little changes, you’ll have to push your git repository back to Openshift so that the latest changes take effect.

Flask_Todo_SQLAlchemy/todo$ git add.
Flask_Todo_SQLAlchemy/todo$ git commit -m "Making it a todo app"
Flask_Todo_SQLAlchemy/todo$ git push

Ensure that everything is still working by visiting the http://todo-.rhcloud.com. When this is succesfully completed, you have a basic app working on Openshift, however we have added no intelligence to it. That’s what we will start doing now…

Defining the Todo model

In the code below, we will first import the SQLAlchemy class and then we will create an instance of it by passing the app object to it. Next we define the todo model by extending db.Model. Essentially, this means that we will have a database that contains a table called ‘todos’ with the fields id, content, done and created_at. We also define a constructor to assign values to the database fields.

from datetime import datetime
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask import Flask, request, flash, url_for, redirect, render_template, abort
  
app = Flask(__name__)
 
app.config.from_pyfile('todo.cfg')
db = SQLAlchemy(app)
 
class Todo(db.Model):
    __tablename__ = 'todos'
    id = db.Column('todo_id', db.Integer, primary_key=True)
    content = db.Column(db.String(60))
    done = db.Column(db.Boolean)
    created_at = db.Column(db.DateTime)
 
    def __init__(self, content):
        self.content = content
        self.done = False
        self.created_at = datetime.utcnow()

Note that we also are referring to todo.cfg in the above code snippet. This file contains the application specific configuration. In the todo.cfg file we will store the SQLAlchemy information for now.

import os
SQLALCHEMY_DATABASE_URI = os.environ['OPENSHIFT_POSTGRESQL_DB_URL']
SQLALCHEMY_ECHO = False
SECRET_KEY = 'secret key'
DEBUG = True

The application file under WSGI folder also will need to be updated by adding the following to it. These entries will ensure that the database will get created on Openshift.

from todoapp import *
db.create_all()

Adding the routes

In the todoapp.py file, we should now start adding the required routes. The below snippet will render the index.html template when peope are visiting the root of your website.

@app.route('/')
def index():
    return render_template('index.html',
        todos=Todo.query.order_by(Todo.created_at.desc()).all()
    )

Flask will always look in the template folder to find the template files. Therefore you will need to first create a directory ‘templates’ under the WSGI folder. Since we didn’t create yet the index.html file under templates, we will do this now. See the index file here

You will see that the index.html file extends layout.html. So we will need to create the layout.html file also. See the layout file here.

The layout.html file contains already the required references to the bootstrap files. Since we haven’t added then to our project, we should do that now. Therefore go to the Bootstrap site and download the files. You will get three folders: css, js and img. Copy these over to the static folder under WSGI. Note that if you don’t have this static folder, you can just create it under the WSGI folder.
Add the files to your git repository and push then to Openshift as follows.

Flask_Todo_SQLAlchemy/todo$ git add.
Flask_Todo_SQLAlchemy/todo$ git commit -m "Making it a todo app"
Flask_Todo_SQLAlchemy/todo$ git push

You should now have a todo application that looks as follows:
Flask_SQLAlchemy_index

Adding new todo items

We will continue by adding the necessary logic and files to be able to insert new todo items. We will first start with adding the /new route to our application. When a new todo item is posted/added, it will be stored in the database.

@app.route('/new', methods=['GET', 'POST'])
def new():
    if request.method == 'POST':
            todo = Todo(request.form['content'])
            db.session.add(todo)
            db.session.commit()
            return redirect('/')
    return render_template('new.html')

In the above snippet, you see that we are rendering the new template, however it is not existing yet. So go ahead and create a new.html file under the templates directory. The new.html file can be seen here.

By now, you know that you have to add it again to Openshift by doing the following sequence:

Flask_Todo_SQLAlchemy/todo$ git add.
Flask_Todo_SQLAlchemy/todo$ git commit -m "Making it a todo app"
Flask_Todo_SQLAlchemy/todo$ git push

Visit the new route on your application on Openshift (in my case http://todo-wymedia.rhcloud.com/new) and you should see the following:
Flask-SQLAlchemy_new

A similar procedure can be followed for the update and delete functions. Since this post is getting quite long, I believe it would be more useful to add it to Github so you can have a quick look. The code can be found on github.