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.
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.
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.
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
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
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:
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==188.8.131.52 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
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"
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:
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'], )
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.
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:
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.