Saturday, August 18, 2012

Launching Flask on Google App Engine (GAE)

In this article i want to highlight some aspects of launching flask framework on GAE platform. I have investigated some time in this platform, and came to conclusion that flask is a good choice for building web applications on Google App Engine platform because this framework is lightweight, flexible and doesn't relate to some special kind of data storage.
So let's get started!
For the beginning you must be familiar with basics of building GAE apps. If you are not - i suggest you to pass "get started" tutorials here (for python2.7). As Google App Engine has already good support for python2.7 i decided to show example based on this version, but  it has almost no differences with 2.5 version example.
Sources are available here






Environment:


At first create empty working dir for project. After you have setup GAE sdk, and added sdk folder to your $PATH varriable you must be able to launch scripts dev_appserver.py and appcfg.py from GAE sdk  in your working dir. Create two empty files app.yaml and main.py inside your working dir.

The second step is installing Flask and it's dependencies. I prefer to use virtualenv, and install packages via pip, but you may install them directly in your working folder by wget, simple copying or something else. If you are not familiar with virtualenv i suggest you to read about it in my previous article about Flask here . So let's create virtualenv with python2.7. Just go to dir with your's virtual environments(if you don't have - mkdir  ~/virt) and initialize new virtual environment:

$ virtualenv gae_flask --python=python2.7. 

Then activate it:

$ . ~/virt/gae_flask/bin/activate

and install Flask:

$ pip install flask

Later we will copy all installed packages from virtualenv's default install folder to our working dir. After installing Flask your environment must be ready for development.

Config file (app.yaml)

Lets fill our app.yaml file:

application : gaeflask
version : 1
runtime : python27
api_version : 1
threadsafe: true

handlers:
- url: /static
  static_dir : gae_flask_app/static
- url: .*
  script : main.app


This file points to start script, static folder, keeps some info about name and version of app, python and api version. More about threadsafe option here

Launch script (main.py)

Before we will write some logic for main.py script i must point that our flask app will be running almost independently of GAE platform as simple WSGI application. So let's create separate package for it and calll it gae_flask_app in our root working dir. This package will contain all application business logic, views, models e. t. c. So, as GAE can launch WSGI app we need to provide it. Lets create app.py file inside of gae_flask_app package. Also we need to copy our installed libs from site-packages folder in our working dir. With my folders structure, site-packages for current virtual environment are in ~/virtual/gae_flask/lib/python2.7/site-packages. For now we must have such file-structure :

/gae_flask:
    /gae_flask_app
        - __init__.py
        - app.py

    app.yaml
    main.py

   /flask
   /werkzeug
   /jinja2

Here is the code for app.py file :
from flask import Flask

def create_app(config):    
    app = Flask(__name__)
    app.config.from_object(config)

    # Later register blueprints here.
    # ...

    return app

Nothing special - simple app factory module. As you can see it accepts settings module and load it to app instance.

The next step is to provide WSGI app handler in main.py module. So this is the contents of my main.py module :

from gae_flask_app.app import create_app
from gae_flask_app import settings

app = create_app(settings)


Here we importing app factory and settings module and launching our app. Don't forget to create settings.py. Let's add one setting line - DEBUG=True. 
So for now you may execute : $ dev_appserver.py .  in working dir and if everything is done correct you will see that applications started on some host and port.

Returning to our DEBUG  setting i must admit that to take full advantage of werkzeug debugger we need to modify our main.py file:
from gae_flask_app.app import create_app
from gae_flask_app import settings
from werkzeug import DebuggedApplication

flask_app = create_app(settings)

if flask_app.config['DEBUG']:
    flask_app.debug = True
    flask_app =  DebuggedApplication(flask_app, evalex=True)

app = flask_app

And up to this point we will be able to use awesome werkzeug debugger in browser.

Let's say "Hello"

There are left a few steps to produce some output to user. Let's add new package inside gae_flask_app folder and call it hello_gae. Besides __init__.py inside of hello_gae let's add handlers.py module to handle our requests(maybe it is not so reasonable to add a separate package for each blueprint... but i use to separate blueprints as independently as possible).
Let's initialize our blueprint in file  __init__.py inside hello_gae package :

from flask import Blueprint

hello_gae = Blueprint('hello_gae', __name__)

import handlers

And after that let's add simple handler to handlers.py:
from ..hello_gae import hello_gae

@hello_gae.route('/')
def hello_gae():
    return "Hello GAE!!!"

As the last step let's register our blueprint in app.py module, to do this let's modify create_app function :

def create_app(config):    
    app = Flask(__name__)
    app.config.from_object(config)

    # Later register blueprints here.
    # ...
    from gae_flask_app.hello_gae import hello_gae
    app.register_blueprint(hello_gae, url_prefix="/")
    return app

For now we a ready to see "Hello GAE" message in browser after launching command dev_appserver.py  .


Templates and Static files

I think you have got the main idea of launching Flask framework on GAE. As for the end, let's add template rendering. Create templates dir in gae_flask_app package and create base.html file there :

<!DOCTYPE html>
<html>
<head>
< link href="/static/style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
  <h1>HELLO FLASK ON GAE!!!</h1>
<div class="css_check">
this must be with border when css file will be included
</div>
</body>
</html>

And here we are testing static files including. Create static dir in gae_flask_app, put there style.css file
.css_check {
  border: 1px solid black;
  padding: 10px;
}

And at last let's modify out handler to display template file :

@hello_gae.route('/')
def hello_gae():
    return render_template("base.html")

If everything was done correctly you will see bordered div in browser output. If something goes wrong - checkout sources from my bitbucket repo.
That's it, now we are have working basic project, and we may build full featured, powerful web app, based on Flask framework on GAE platform.

Maybe i had fallen too deep in details in this tutorial, but i remember when i was only starting to write something on GAE, i missed such kind of detailed tutorial.
Have a good luck in creating your own projects, hope this article will help someone to get started.