Starting a Flask Application, ft. Heroku

Ease-of-use framework: meet ease-of-use platform

We all knew it would only be a matter of time before a blog full of Python junkies would touch on Python's fastest growing framework. Staying true to all that is Pythonic, Flask is a gift to developers who value the act of development. By minimizing level of effort and maximizing potential, Flask allows us to be as minimalist (or obnoxiously complex) as we want.

Why Flask?

Those of us who grew up loving Django have embraced Flask with a hint of disbelief, in that Flask is both shockingly simple and surprisingly powerful. Whereas the initial setup of a Django project could easily take hours, Flask's set up is merely a copy+paste of the following:

from flask import Flask
app = Flask(__name__)

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

Saving those 5 lines into an app.py file is a functioning flask app in itself.

While it's possible to create an entire flask application as one file, Flask is just as extensible as its predecessors, depending on the creator's will. Not only does this make Flask projects feel more expressive, as they are a reflection of the creator's development philosophy, but the simplicity is just plain fun.

For those familiar with ExpressJS, I'd be so bold as to say that Flask is even more simple than Express. Depending on your development philosophy, Flask can execute comparable functionality to Express with significantly less code.

But Why Heroku?

We're on the topic of simplicity, so let's keep that theme going. Heroku's infrastructure offering  is the most unique of all major cloud providers, in that Heroku obfuscates the the DevOps aspect of web development completely. That means that configuring web servers, managing Linux packages, and supplying SSL certs are completely taken care of by Heroku. Let's consider this a luxury for our time, as opposed to a replace for grasping this concepts.

Sorry, that was the old man in me speaking; back in my day, I was just happy just to get a plain Linux box for 20 bucks a month. Don't even get me started on CPanel.

Aside from VPS upkeep, Heroku obfuscates the process of moving an app through development and production environments by defining pipelines. So you can basically go ahead and fire all your PMs and DevOps guys if you haven't already. I think that was a joke but I'm not entirely sure anymore.

An example Heroku Pipeline.

Finally, the most impressive concept we're being offered here are Elements. Heroku holds a 'marketplace' of popular add-ons ranging from databases to analytics; all of which can be configured to interact with your deployed app after with minimal configuration and a single click.

Speaking of single-click, they handle single-click deployments of popular build packs, too. You get the idea.

Creating your Project

Log in to the Heroku UI and create an app on a fresh Dyno: this is an encapsulated instance of your application. Next you'll be prompted to download the Heroku CLI locally on your OS of choice, which is quick and painless. Now we're cookin' with gas

Create an empty local directory and type the following command to be prompted for your Heroku account credentials:

$ heroku login
Enter your Heroku credentials.
Email: [email protected]
Password:

At this point, Heroku has already magically created a git repository for your application from which you'll be doing development from.

$ git clone https://github.com/heroku/example-flask-project.git
$ cd example-flask-project

$ heroku create
Creating example-flask-project in organization heroku... done, stack is cedar-14
http://example-flask-project.herokuapp.com/ | https://git.heroku.com/example-flask-project.git
Git remote heroku added

Wow, that sure looks a lot like we're working with Github huh? That's actually the point: if you so chose, you can configure the Heroku CLI to recognize your Github username with a simple heroku config:get GITHUB_USERNAME=yourname. With this configured, Heroku will actually allow you to simply deploy to your personal Gihub repo and mimic the changes on your Dyno.Now let's configure this thing.

A Project For Ants

We're going to go step-by-step to build out the most simply application configuration imaginable:

example-flask-project
├── app.py
├── Procfile
├── Pipfile
├── Pipfile.lock
├── runtime.txt
├── requirements.txt
├── Pipfile.lock
└── setup.py

For the love of all that is holy, use Pipenv to manage your packages. We'll need it.

$ pip install pipenv
pipenv shell

Install your basic dependencies while in the shell:

$ pip3 install flask gunicorn

Awesome. Now let's build out the files in our tree one-by one.

Procfile

The Procfile (no file extension) is a unique file to Heroku which is essentially an build command. This will be a single-liner to tell gunicorn to startup our application from our base app.py file.

web: gunicorn app:app

A quick breakdown here: web is our process 'type'. other types exists, such as worker, urgentworker, and clock, but that's not important for now.

app:app signifies looking for the 'app' module in our app.py file. If you'd like to move app.py to . a different folder down the line, this can be adjusted as such:

web: gunicorn differentfolder app:app

Runtime

The runtime.txt file simply notifies Heroku of the language it's dealing with as well as the proper version. This is simple, because you can can only have one possible value here:

python-3.6.6

Requirements.txt

Think of this as Python's package.json for package dependencies. Keep this updated when you change your packages by entering the following in the pipenv shell:

pip freeze > requirements.txt

This will immediately all packages and their versions in the file, as such:

asn1crypto==0.24.0
bcrypt==3.1.4
beautifulsoup4==4.6.0
blinker==1.4
cffi==1.11.5
click==6.7
cryptography==2.2.2
Flask==1.0.2
Flask-Assets==0.12
Flask-Login==0.4.1
Flask-Mail==0.9.1
flask-mongoengine==0.9.5
Flask-SQLAlchemy==2.3.2
Flask-Static-Compress==1.0.2
Flask-User==1.0.1.5
Flask-WTF==0.14.2
gunicorn==19.9.0
idna==2.7
itsdangerous==0.24
jac==0.17.1
Jinja2==2.10
MarkupSafe==1.0
mongoengine==0.15.0
ordereddict==1.1
passlib==1.7.1
pycparser==2.18
pymongo==3.7.0
rjsmin==1.0.12
six==1.11.0
SQLAlchemy==1.2.9
webassets==0.12.1
Werkzeug==0.14.1
WTForms==2.2.1

Pipfile

Our Pipfile is automatically generated by Pipenv by default, but be sure to call out packages which are essential to the build our app as. This will rarely need to be updated manually:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
gunicorn = "*"
flask = "*"
requests = "*"
wtforms = "*"
flask_assets = "*"
flask_static_compress = "*"

[dev-packages]

[requires]
python_version = "3.6.6"

Pipfile.lock

Heroku looks at Pipfile.lock every time our app builds to know which packages to install on the server side. Changing dependancies locally without updating the pipfile.lock will not carry the changes over to your Dyno. Thus, be sure to generate this file when needed:

pipenv lock

Setup.py

Just some general info.

from setuptools import setup, find_packages

setup(
    name='example-flask-project',
    version='1.0',
    long_description=__doc__,
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    install_requires=['Flask'],
)

.env

Okay, okay, just one last thing. Heroku will be upset unless there's a .env file in its root directory at run time. Feel free to just leave this empty for now.

Deployment

Running your app locally is as simple as two words: heroku local. This spins up an instance of your app at 0.0.0.0:5000.

Deploying to your Heroku Dyno is much like deploying to Github (they can in fact be the exact same if you configure it as such). Here's how deployment via the Heroku CLI looks:

git add .
git commit -am 'initial commit'
git push heroku master

If all went well, your app should be live at the URL Heroku generated for you when you created your project. Go ahead and checkout the Heroku UI to see how things went.

I highly suggest checking out the logs on the Heroku UI after each deploy. Often times issues which don't appear on your local environment will pop up on the server:

Heroku's UI logs

Quick Emotional Sanity Check

Truthfully, I'm not entirely sure if the point I'm trying to make in this post is that Heroku is fun, or that Flask is awesome. Both are true, but there's probably been enough said about Heroku already.

While Flask's development may not be as vast as the npm packages offered by Node, there's more or less a package for anything you possibly need. I'd recommend checking out Flask's official list of packages .

While we may have set up our first Flask application, as it stands we've only built something useless so far. Consider this to be the beginning of many, many Flask tips to come.

Author image
New York City Website
Product manager turned engineer with an ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.

Product manager turned engineer with an ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.