Lightweight Python Apps with Flask, Bootstrap, and Heroku

Welcome! This is a quick start guide for easily and quickly deploying python apps.

The goal of this guide is to provide you with a simple, step-by-step flow that you can follow when building small, simple apps from the ground up (which can later turn into large, complex apps). Each technology, including Heroku, Flask, and Twitter Bootstrap, has been carefully chosen to make the process as simple, quick, and painless as possible.

Please note that this guide does not explain every step in detail, and assumes you have at some point interacted with either a few of these technologies or related ones. For absolute beginners, I would recommend first heading over to the respective sites for flask and flask on heroku to get a little more acquianted.

Now for a little introduction about the design decisions made in this quick start guide:

Flask is a popular lightweight python framework (or micro-framework), allowing you to develop simple apps extremely quickly. It is also a great choice for beginners to python web development, considering it is:

  • dead simple to start out: you can build a "hello world" app in 7 lines, in a single file, without the need for folders and folders of files just to get started (some frameworks auto-generate a boatload of files that are completely foreign to you until you really dig deep)
  • simple but extensible = manageable learning curve: you can bite off little bits of the framework at a time and learn as you go, safe from feeling suddenly overwhelmed
  • easy to understand: you can just write python code and know what you're writing, without needing to learn an entire new pseudo-language
  • well-documented: the quick start guide, tutorial, and other docs are well-written and extensive

Heroku is above and beyond the best choice for a lone developer or small team, especially considering it is:

  • dead simple to start out: "heroku create --stack cedar" to create an app and "git push heroku master" to deploy code
  • economical: you pay nothing until you exceed the traffic that a single instance can handle (and it's pretty cheap thereafter)
  • easy to manage: it features a panel with all of your apps, as well as a simple system to scale up and integrate additional technologies

Twitter Bootstrap is nice to start out because, well, you don't really have to do much to make the site look pretty damn good. Yes, it is cookie-cutter and clearly you will want to put some more work into the design soon enough, but for the first few hours or even days of development, integrating Twitter Bootstrap is a wise move.

One last order of business before we begin - this quick start guide is split up into sections that correspond with distinct tasks in the app development process and assumes you already have:

  • a heroku account
  • the heroku toolbelt
  • a github account
  • python installed
  • virtualenv installed
  • pip installed

If you are missing one or more of these, please get them set up before moving on.

Alright, now that we've gotten all of that out of the way, let's get started!

create github repo

sign in to your github account (which we'll refer to from now on as YOUR_GITHUB_USERNAME)

create and name your new repository (which we'll refer to as MY_NEW_APP)

create local git repo

mkdir MY_NEW_APP

cd MY_NEW_APP

git init

touch README.md

git add README.md

git commit -m 'first commit'

git remote add origin https://github.com/YOUR_GITHUB_USERNAME/MY_NEW_APP.git

git push -u origin master

create .gitignore

*.pyc
venv
*~
.DS_Store

create app.py

import os
from flask import Flask

# initialization
app = Flask(__name__)
app.config.update(
    DEBUG = True,
)

# controllers
@app.route("/")
def hello():
    return "Hello from Python!"

# launch
if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)

create virtualenv

virtualenv venv --distribute

source venv/bin/activate

pip install Flask

"pip install" anything else you need (Flask-OAuth, Flask-Mail, etc.)

create requirements.txt

pip freeze > requirements.txt

check to make sure the pip freeze worked: "cat requirements.txt"

create Procfile

web: python app.py

note that if the Procfile is not included, nothing will work

test out the app with "foreman start"

create heroku app

heroku create --stack cedar

heroku apps:rename MY_NEW_APP

git add .

"git status" will let you see what files you have yet to commit

git commit -m "adding in basic files"

git push heroku master

heroku ps:scale web=1

check to make sure the app is up and running: "heroku ps"

check the logs for errors, misc. output, a history of http requests, etc: "heroku logs"

add static folder

mkdir static static/css static/js static/img static/ico

create favicon.ico file at favicon.cc and add to static/ico

add any necessary css, js, and img files

add templates folder

mkdir templates

this is where you should put all subsequent .html files

create base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    {% block head %}
    <title>SuperApp{% block title %}{% endblock %}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="keywords" content="">
    <meta name="author" content="">
    <meta charset="utf-8">

    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
    <link rel="shortcut icon" href="{{ url_for('static', filename='ico/favicon.ico') }}">
    {% endblock %}
  </head>
  <body>
    {% block navbar %}
    <div class="navbar navbar-static-top navbar-default">
      <div class="container">
        <button class="navbar-toggle">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="/">SuperApp</a>
        <div class="nav-collapse">
          {% block navbar_right %}
          <ul class="nav navbar-nav pull-right">
            {% if not session.logged_in %}
              <li><a href="#">Login or Signup</a></li>
            {% else %}
              <li><a href="#">Logout</a></li>
            {% endif %}
          </ul>
          {% endblock %}
        </div><!--/.nav-collapse -->
      </div>
    </div>
    {% endblock %}
    <div class="container page">
        <div class="content">
          {% block content %}
          {% endblock %}
        </div>
        <hr>
        {% block footer %}
        <footer class="footer">
            <p>&copy; SuperApp</p>
        </footer>
        {% endblock %}
    </div>
    {% block js_footer %}
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
      <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
    {% endblock %}
  </body>
</html>

create index.html

{% extends "base.html" %}
{% block title %} - Home{% endblock %}
{% block content %}
{% if not session.logged_in %}
     <p>You are not logged in.</p>
{% else %}
     <p>You are logged in.</p>
{% endif %}
{% endblock %}

create 404.html

{% extends "base.html" %}
{% block title %} - Page Not Found{% endblock %}
{% block content %}
  <h1>Page Not Found</h1>
  <p><a href="{{ url_for('index') }}">home</a></p>
{% endblock %}

update the index controller and add 404 and favicon handlers

update the controller section to

# controllers
@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'), 'ico/favicon.ico')

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

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

As you can see, we've not only updated the home controller - we've also added a 404 handler and routing for the favicon we added earlier.

update the line

from flask import Flask

to

from flask import Flask, render_template, send_from_directory

incorporate other technologies

Did you find this post helpful?

I'd love to hear your thoughts - just drop me a line on twitter or leave a comment in the space below.

Ryan Shea

Co-Founder of OneName.io. Hacking on Bitcoin. Trying to build the identity layer of the Internet.


comments powered by Disqus