Skip to content

Instantly share code, notes, and snippets.

@rosiehoyem
Last active April 2, 2017 22:21
Show Gist options
  • Save rosiehoyem/05a6961a72b3acb02e6857e9a29b41a4 to your computer and use it in GitHub Desktop.
Save rosiehoyem/05a6961a72b3acb02e6857e9a29b41a4 to your computer and use it in GitHub Desktop.
Minimally Viable Flask Application

This is a tutorial for a mini data science quiz app that we will deploy to Heroku. You'll find the completed code here.

This simple app is based on the gettting started tutorial from the framework's creators, Pocoo.

0. Install Flask

If you're an Anaconda user, run:

conda install flask

Or if you prefer pip,

pip install flask

1. Set up the folder structure

/quizr
    /quizr
        /static
        /templates

mkdir quizr

cd quizr

mkdir quizr

cd quizr

mkdir static

mkdir templates

2. Create the database schema

Just kidding. We don't need a database. We're going to use Google docs! The spreadsheet we will use lives here.

3. Create the configs, controller, route, and model

In quizr/quizr.py copy and paste the following code:

import os
import pandas as pd
import numpy as np
from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash
app = Flask(__name__) # create the application instance :)

app.config.from_object(__name__) # load config from this file , quizr.py

app.config.update(dict(
    SECRET_KEY='development key',
))
app.config.from_envvar('QUIZR_SETTINGS', silent=True)

def get_vocab():
    base = "https://docs.google.com/spreadsheets/d/"
    doc_id = "13uFW3lriigsAKJTAn_Ilo3fo7ZdeLUKbtqOe65Bf4iw"
    export_sheet = "/export?gid=577814466&format=csv"
    url = base + doc_id + export_sheet
    vocab = pd.read_csv(url,index_col=False)
    sample = vocab.sample(10)
    return sample.to_dict(orient = "records")
    
@app.route('/')
def index():
    vocab = get_vocab()
    return render_template('index.html', vocab=vocab)

4. Add init, setup, and manifest files

/quizr
    /quizr
        __init__.py
        /static
        /templates
        quizr.py
    setup.py
    MANIFEST.in

Create the setup file.

touch setup.py

Copy and paste this content.

from setuptools import setup

setup(
    name='quizr',
    packages=['quizr'],
    include_package_data=True,
    install_requires=[
        'flask',
    ],
)

Create the manifest file.

touch MANIFEST.in

Copy and paste this content.

graft quizr/templates
graft quizr/static

Create the init file.

touch quizr/__init__.py

Copy and paste this content.

from .quizr import app

4. Create the index template.

touch quizr/templates/index.html

Paste this content. We're making a single page app, so we only need one template.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Quizr</title>
    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap.css') }}">
    <!-- Custom styles for this template -->
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='jumbotron-narrow.css') }}">
  </head>
  <body>
    <div class="container">
      <div class="header clearfix">
        <h3 class="text-muted">Quizr</h3>
      </div>

      <div class="jumbotron">
        <h1>Data Science Quizr</h1>
        <p class="lead">Get your DS quiz fix at home. Your welcome.</p>
        <p><a class="btn btn-lg btn-success" href="{{ url_for('index') }}" role="button">Refresh the list</a></p>
      </div>
      {% for item in vocab %}
      <div class="panel panel-default">
        <div class="panel-heading">
          <div class="pull-right">
            <button class="btn btn-info btn-sm" type="button" data-toggle="collapse" href="#collapseExample{{loop.index0}}" aria-expanded="false" aria-controls="collapseExample">
              Show Definition
            </button>
          </div>
          <h3 class="panel-title">{{ item.term }}</h3>
          <br/>
        </div>
        <div class="panel-body">
          <div class="collapse" id="collapseExample{{loop.index0}}">
            <div class="well">
              {{ item.definition }}
            </div>
          </div>
        </div>
      </div> 
      {% endfor %}
      <footer class="footer">
        <p>&copy; 2016 Rosie, Inc.</p>
      </footer>
    </div>
    <script src="https://code.jquery.com/jquery-2.2.4.js" integrity_no="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI=" crossorigin="anonymous"></script>
    <script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
  </body>
</html>

5. Add CSS and JS.

Drop these file into quizr/static. We're using the core Bootstrap library as well as a Bootstrap theme and layout. Though it is true that adding the whole Bootstrap libray adds a huge pile of code that we won't be using, for the sake of keeping the creation of this app simple, we're just going to grab the whole thing.

Bootstrap JS

Bootstrap Simplex Theme CSS

Bootstrap Jumbo Narrow Layout Theme

6. Install the application and get it up and running

pip install --editable .

export FLASK_APP=quizr

export FLASK_DEBUG=true

flask run

Your app should now be running locally. Let's take a look. Open a web browser and go to localhost:5000.

http://localhost:5000/

7. Commit your new app to Github.

Don't forget to create a new Github repo and commit your changes.

git init

git add .

git commit -m 'created new awesome flask app'

git push

8. Create a new Heroku instance

After you've created a Heroku account and installed the Heroku toolbelt, you're ready to create an app in the cloud. Log into your account from the command line and run:

heroku apps:create metis-quizr

Note that the name of the app must be unique. metis-quizr is already taken, so use a variation.

9. Prepare your app for deployment

Heroku requires a few more things to be included in your app before deployment.

Create a Procfile in the root of your app.

touch Procfile

Copy and paste this content.

web: gunicorn quizr:app

Next we need to create a requirements.txt file with all of the dependencies. pipreqs will help us do this. To install, this package, run:

pip install pipreqs

Then to automatically create this file, run this from the root of your app:

pipreqs .

This will included most of our dependencies. We'll be using gunicorn on Heroku, so add it to your requirements.txt file as well. The setuptools entry is not required for deployment. That can be removed. It should now look like this:

Flask==0.12
gunicorn==19.0.0
numpy==1.11.3
pandas==0.19.1

We also need to tell Heroku what version of python we are using. Create a runtime.txt file also in the root of your app to do this.

touch runtime.txt

And paste your version of python.

python-3.5.2

Now, we can commit our changes, push to Github.

git add .

git commit -m "added files for deployment to Heroku"

git push

10. Deploy!

We're ready to deploy our cool app to the new Heroku instance we made in step 8. This is easy, just run:

git push heroku master

Almost done. Now, scale upto one web dyno.

heroku ps:scale web=1

Restart Heroku:

heroku restart

And open up your shiny new app!

heroku open

TADA!! You should have a shiny new application running on Heroku.

Resources

More Resources on deployment:

Here's instructions from Heroku.

Here's another approach from a tutorial.

The approach I take here is a simplied version.

Have an app with more dependencies? Try using a buildpack.

heroku config:add BUILDPACK_URL=https://github.com/buildingspeak/conda-buildpack.git

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment