Getting Started With Flask, A Python Microframework

Flask can help speed up Python development for your projects.

Flask is a simple, easy-to-use microframework for Python that can help build scalable and secure web applications. Here are a few reasons why Flask is great for beginners:

  1. It's easy to set up
  2. It's supported by an active community
  3. It's well documented
  4. It's very simple and minimalistic, and doesn't include anything you won't use
  5. At the same time, it's flexible enough that you can add extensions if you need more functionality

In this tutorial, we'll cover the following:

  1. Installation of Flask and its prerequisites
  2. Recommended file and directory structure for a Flask project
  3. Configuration and initialization of a Flask app
  4. Creating views and templates

By the end of this tutorial, we will have built a simple static website using Flask. The code used in this tutorial is available for your reference on GitHub.

Ready? Let's dive in!

Installation

We'll need the following installed for this tutorial:

  1. Python (this tutorial uses Python 2)
  2. virtualenv and virtualenvwrapper
  3. Flask

You may already have Python installed on your system. You can check by running the python command in your terminal. If it's installed, you should see the following output:

$ python
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

If you don't have it installed, you can download it here.

We'll start by installing virtualenv, a tool to create isolated Python environments. We need to use virtual environments to keep the dependencies used by different Python projects separate, and to keep our global site-packages directory clean. We'll go one step further and install virtualenvwrapper, a set of extensions that make using virtualenv a whole lot easier by providing simpler commands.

$ pip install virtualenv
$ pip install virtualenvwrapper
$ export WORKON_HOME=~/Envs
$ source /usr/local/bin/virtualenvwrapper.sh

To create and activate a virtualenv, run the following commands:

$ mkvirtualenv my-venv
$ workon my-venv

Told you the commands were simple! We now have a virtualenv called my-venv, which we have activated and are currently working on. Now, any dependencies we install will be installed here and not globally. Remember to activate the virtualenv whenever you want to use or work on this project!

Next, let's create a directory for our app. This is where all our files will go:

$ mkdir my-project
$ cd my-project

Finally, let's install Flask:

$ pip install Flask

Installing Flask also installs a few other dependencies, which you will see when you run the following command:

$ pip freeze
click==6.6
Flask==0.11.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
Werkzeug==0.11.11

What do all these packages do? Flask uses Click (Command Line Interface Creation Kit) for its command-line interface, which allows you to add custom shell commands for your app. ItsDangerous provides security when sending data using cryptographical signing. Jinja2 is a powerful template engine for Python, while MarkupSafe is a HTML string handling library. Werkzeug is a utility library for WSGI, a protocol that ensures web apps and web servers can communicate effectively.

You can save the output above in a file. This is good practice because anyone who wants to work on or run your project will need to know the dependencies to install. The following command will save the dependencies in a requirements.txt file:

pip freeze > requirements.txt

Say "Hello World!" with Flask

I think any beginner programming tutorial would be remiss if it didn't start with the classic "Hello World!" So here's how to do this in Flask:

Create the following file, hello_world.py, in your favourite text editor (I'm an Atom girl, myself):

# hello_world.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

We begin by importing the Flask class, and creating an instance of it. We use the __name__ argument to indicate the app's module or package, so that Flask knows where to find other files such as templates. Then we have a simple function that will display the string Hello World!. The preceeding decorator simply tells Flask which path to display the result of the function. In this case, we have specified the route /, which is the home URL.

Let's see this in action, shall we? In your terminal, run the following:

$ export FLASK_APP=hello_world.py
$ flask run
 * Serving Flask app "hello_world"
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

The first command tells the system which app to run. The next one starts the server. Enter the specified URL (http://127.0.0.1:5000/) in your browser. Voila! It works!

Directory Structure

So far, we only have one functional file in our project: hello_world.py. A real-world web project usually has more files than that. It's important to maintain a good directory structure, so as to organize the different components of the application separately. These are a few of the common directories in a Flask project:

  1. /app: This is a directory within my-project . We'll put all our code in here, and leave other files, such as the requirements.txt file, outside.
  2. /app/templates: This is where our HTML files will go.
  3. /app/static: This is where static files such as CSS and JavaScript files as well as images usually go. However, we won't be needing this folder for this tutorial since we won't be using any static files.
$ mkdir app app/templates

Your project directory should now look like this:

├── my-project
       ├── app
       │   ├── templates
       ├── hello_world.py
       └── requirements.txt

The hello_world.py seems a little out of place now, doesn't it? Don't worry, we'll fix that in the next section.

File Structure

For the "Hello World!" example, we only had one file. To build our website, we'll need more files that serve various functions. Most Flask apps have the following basic file structure:

  1. run.py: This is the application's entry point. We'll run this file to start the Flask server and launch our application.
  2. config.py: This file contains the configuration variables for your app, such as database details.
  3. app/__init__.py: This file intializes a Python module. Without it, Python will not recognize the app directory as a module.
  4. app/views.py: This file contains all the routes for our application. This will tell Flask what to display on which path.
  5. app/models.py: This is where the models are defined. A model is a representation of a database table in code. However, because we will not be using a database in this tutorial, we won't be needing this file.

Some projects have more modules (for example, an app/views directory with many views files in it), but this'll do for now. Go ahead and create these files, and delete hello_world.py since we won't be needing it anymore:

$ touch run.py config.py
$ cd app
$ touch __init__.py views.py
$ rm hello_world.py

Here's our latest directory structure:

├── my-project
       ├── app
       │   ├── __init__.py
       │   ├── templates
       │   └── views.py
       ├── config.py
       ├── requirements.txt
       └── run.py

Now let's fill these empty files with some code!

Configuration

The config.py file should contain one variable per line, like so:

# config.py

# Enable Flask's debugging features. Should be False in production
DEBUG = True

Note that this config file is very simplified and would not be appropriate for a more complex application. For bigger applications, you may choose to have different config.py files for testing, development, and production, and put them in a config directory, making use of classes and inheritance. You may have some variables that should not be publicly shared, such as passwords and secret keys. These can be put in an instance/config.py file, which should not be pushed to version control.

Initialization

Next, we have to initialize our app with all our configurations. This is done in the app/__init__.py file. Note that if we set instance_relative_config to True, we can use app.config.from_object('config') to load the config.py file.

# app/__init__.py

from flask import Flask

# Initialize the app
app = Flask(__name__, instance_relative_config=True)

# Load the views
from app import views

# Load the config file
app.config.from_object('config')

Run, Flask, Run!

All we have to do now is configure our run.py file so we can start the Flask server.

# run.py

from app import app

if __name__ == '__main__':
    app.run()

To use the command flask run like we did before, we would need to set the FLASK_APP environment variable to run.py, like so:

$ export FLASK_APP=run.py
$ flask run

We'll get a 404 page because we haven't written any views for our app. We'll be fixing that shortly.

Views

From the "Hello World!" example, you already have an understanding of how views work. We use the @app.route decorator to specify the path we'd like the view to be dispayed on. We've already seen how to write a view that returns a string. Let's see what else we can do with views.

# views.py

from flask import render_template

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

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

Flask provides a method, render_template, which we can use to specifiy which HTML file should be loaded in a particular view. Of course, the index.html and about.html files don't exist yet, so Flask will give us a Template Not Found error when we navigate to these paths. Go ahead; run the app and see:

Templates

Flask allows us to use a variety of template languages, but Jinja2 is by far the most popular one. Remember it from our installed dependencies? Jinja provides syntax that allows us to add some functionality to our HTML files, like if-else blocks and for loops, and also use variables inside our templates. Jinja also lets us implement template inheritance, which means we can have a base template that other templates inherit from. Cool, right?

Let's begin by creating the following three HTML files:

$ cd app/templates
$ touch base.html index.html about.html

We'll start with the base.html file, using a slightly modified version of this example Bootstrap template:

<!-- base.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{% block title %}{% endblock %}</title>
    <!-- Bootstrap core CSS -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="https://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header clearfix">
        <nav>
          <ul class="nav nav-pills pull-right">
            <li role="presentation"><a href="/">Home</a></li>
            <li role="presentation"><a href="/about">About</a></li>
            <li role="presentation"><a href="http://flask.pocoo.org" target="_blank">More About Flask</a></li>
          </ul>
        </nav>
      </div>
      {% block body %}
      {% endblock %}
      <footer class="footer">
        <p>© 2016 Your Name Here</p>
      </footer>
    </div> <!-- /container -->
  </body>
</html>

Did you notice the {% block %} and {% endblock %} tags? We'll also use them in the templates that inherit from the base template:

<!-- index.html-->

{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block body %}
<div class="jumbotron">
  <h1>Flask Is Awesome</h1>
  <p class="lead">And I'm glad to be learning so much about it!</p>
</div>
{% endblock %}
<!-- about.html-->

{% extends "base.html" %}
{% block title %}About{% endblock %}
{% block body %}
<div class="jumbotron">
  <h1>The About Page</h1>
  <p class="lead">You can learn more about my website here.</p>
</div>
{% endblock %}

We use the {% extends %} tag to inherit from the base template. We insert the dynamic content inside the {% block %} tags. Everything else is loaded right from the base template, so we don't have to re-write things that are common to all pages, such as the navigation bar and the footer.

Let's refresh our browser and see what we have now:

Conclusion

Congratulations for making it this far and getting your first Flask website up and running! I hope this introduction to Flask has whetted your appetite for exploring more. You now have a great foundation to start building more complex apps. Do have a look at the official documentation for more information.

Have you used other Python frameworks before? Where do you think Flask stands? Let's have a conversation in the comments below.

Mbithe Nzomo

I am a software developer at Andela. I work primarily with Python, and have experience with frameworks such as Django and Flask. I am currently learning JavaScript and ReactJS.

I love getting more women interested in technology and programming! I co-organised Django Girls Nairobi 2016, a free programming workshop for women who've never coded before, and co-led a session on Continuous Integration and Continuous Deployment at the AkiraChix African Women in Tech Conference 2016.