February 20, 2014

Set up Flask with webassets

A fresh python web app with all the fixins: Sass and Coffeescript

Flask isn’t new, but it’s really great, and it’s definitely my first choice when starting a new Python app. Today I want to give you a quick tour of the tools I use to set up a new Flask app.

I’ll do things nice and step-by-step so you can follow along easily. All the code is on github, too.

Getting started

You will need these package managers to install some of these tools. We don’t discriminate here.

Now, we want to make a virtualenv (You’ll need virtualenv). Make a new directory to put your project in, then:

$ virtualenv .env
$ .env/bin/activate

Flask Skeleton

We’ll just make a quick app.py to keep us company. First, install flask:

$ pip install flask

Open up app.py and put this in it:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello World"

if __name__ == "__main__":
    app.run(debug=True)

Preprocessing

I’ve gotten picky about my tools over the years, so here’s what I’m going to demand:

To accomplish that, we’ll use Flask-Assets, which is a thin wrapper around webassets.

So first, let’s install those. This is what we needed npm and gem for. Install sass and coffeescript globally. (We’ll also install Bower for later).

$ sudo gem install sass
$ sudo npm install -g bower coffee-script

From there, we can install some things we’ll probably need. But first, let’s think about the what our project structure will look like. In this case, it’ll be pretty much a standard Flask loadout with the addition of bower. But, we’ll also put our sass and coffeescript files outside the static directory; no need to serve those. So go ahead and make these folders in your project root:

static/
templates/
coffee/
sass/

Now, go into coffee and sass and create all.coffee and all.sass respectively.

We already installed bower to help us manage our client-side packages. Let’s also go ahead and install jquery:

$ bower init
... fill out the questionnaire ...
$ bower install -S jquery

The -S in the latter command will cause the these dependencies to be saved to your bower.json file. You’ll also find that a bower_components folder has magically appeared, containing jquery.

Finally, let’s install Flask-Assets:

$ pip install flask-assets

Next, we’ll need to define our resource bindles. Open up app.py and we can configure webassets:

import os
from flask import Flask, render_template
from flask.ext import assets

app = Flask(__name__)

env = assets.Environment(app)

# Tell flask-assets where to look for our coffeescript and sass files.
env.load_path = [
    os.path.join(os.path.dirname(__file__), 'sass'),
    os.path.join(os.path.dirname(__file__), 'coffee'),
    os.path.join(os.path.dirname(__file__), 'bower_components'),
]


env.register(
    'js_all',
    assets.Bundle(
        'jquery/dist/jquery.min.js',
        assets.Bundle(
            'all.coffee',
            filters=['coffeescript']
        ),
        output='js_all.js'
    )
)

env.register(
    'css_all',
    assets.Bundle(
        'all.sass',
        filters='sass',
        output='css_all.css'
    )
)


@app.route("/")
def index():
    return render_template('index.html')


if __name__ == "__main__":
    app.run(debug=True)

Above, we tell webassets about all of our script files, and all of our stylesheets. Each Bundle can have a filter applied; we use this fact to apply coffeescript and sass to our files. In the js bundle, we nest the coffeescript files in a bundle within the main one, so as to only apply the coffeescript filter to the coffeescript files.

If all worked according to plan, when you run your application…

$ python app.py

… you will find that your static folder has js_all.js and css_all.css in it.

Now, all that’s left to do is to get your assets into a template. As per Flask-Assets’ instructions, just put the following in a template:

<!doctype html>
<html>
    <head>
        <title>Hello Flask</title>
        {% assets "css_all" %}
            <link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}"></script>
        {% endassets %}
    <head>
    <body>
        <h1>Hello Flask</h1>
        {% assets "js_all" %}
            <script type="text/javascript" src="{{ ASSET_URL }}"></script>
        {% endassets %}
    </body>
</html>

And that’s it! Anything you put in sass/all.sass or coffee/all.coffee will be updated when you load the page.

If you’d like to grab a copy of this code to use as a starting point for your next project, you can find it on github. Enjoy!