The Flask Mega-Tutorial, Part I: Hello, World! (2012)

Posted by
on under

(Great news! There is a new version of this tutorial!)

This is the first article in a series where I will be documenting my experience writing web applications in Python using the Flask microframework.

NOTE: This article was revised in September 2014 to be in sync with current versions of Python and Flask.

Here is an index of all the articles in the series that have been published to date:

My background

I'm a software engineer with double digit years of experience developing complex applications in several languages. I first learned Python as part of an effort to create bindings for a C++ library at work.

In addition to Python, I've written web apps in PHP, Ruby, Smalltalk and believe it or not, also in C++. Of all these, the Python/Flask combination is the one that I've found to be the most flexible.

UPDATE: I have written a book titled "Flask Web Development", published in 2014 by O'Reilly Media. The book and the tutorial complement each other, the book presents a more updated usage of Flask and is, in general, more advanced than the tutorial, but some topics are only covered in the tutorial. Visit http://flaskbook.com for more information.

The application

The application I'm going to develop as part of this tutorial is a decently featured microblogging server that I decided to call microblog. Pretty creative, I know.

These are some of the topics I will cover as we make progress with this project:

  • User management, including managing logins, sessions, user roles, profiles and user avatars.
  • Database management, including migration handling.
  • Web form support, including field validation.
  • Pagination of long lists of items.
  • Full text search.
  • Email notifications to users.
  • HTML templates.
  • Support for multiple languages.
  • Caching and other performance optimizations.
  • Debugging techniques for development and production servers.
  • Installation on a production server.

So as you see, I'm going pretty much for the whole thing. I hope this application, when finished, will serve as a sort of template for writing other web applications.

Requirements

If you have a computer that runs Python then you are probably good to go. The tutorial application should run just fine on Windows, OS X and Linux. Unless noted, the code presented in these articles has been tested against Python 2.7 and 3.4, though it will likely be okay if you use a newer 3.x release.

The tutorial assumes that you are familiar with the terminal window (command prompt for Windows users) and know the basic command line file management functions of your operating system. If you don't, then I recommend that you learn how to create directories, copy files, etc. using the command line before continuing.

Finally, you should be somewhat comfortable writing Python code. Familiarity with Python modules and packages is also recommended.

Installing Flask

Okay, let's get started!

If you haven't yet, go ahead and install Python.

Now we have to install Flask and several extensions that we will be using. My preferred way to do this is to create a virtual environment where everything gets installed, so that your main Python installation is not affected. As an added benefit, you won't need root access to do the installation in this way.

So, open up a terminal window, choose a location where you want your application to live and create a new folder there to contain it. Let's call the application folder microblog.

If you are using Python 3, then cd into the microblog folder and then create a virtual environment with the following command:

$ python -m venv flask

Note that in some operating systems you may need to use python3 instead of python. The above command creates a private version of your Python interpreter inside a folder named flask.

If you are using any other version of Python older than 3.4, then you need to download and install virtualenv.py before you can create a virtual environment. If you are on Mac OS X, then you can install it with the following command:

$ sudo easy_install virtualenv

On Linux you likely have a package for your distribution. For example, if you use Ubuntu:

$ sudo apt-get install python-virtualenv

Windows users have the most difficulty in installing virtualenv, so if you want to avoid the trouble then install Python 3. If you want to install virtualenv on Windows then the easiest way is by installing pip first, as explaned in this page. Once pip is installed, the following command installsvirtualenv`:

$ pip install virtualenv

We've seen above how to create a virtual environment in Python 3. For older versions of Python that have been expanded with virtualenv, the command that creates a virtual environment is the following:

$ virtualenv flask

Regardless of the method you use to create the virtual environment, you will end up with a folder named flask that contains a complete Python environment ready to be used for this project.

Virtual environments can be activated and deactivated, if desired. An activated environment adds the location of its bin folder to the system path, so that for example, when you type python you get the environment's version and not the system's one. But activating a virtual environment is not necessary, it is equally effective to invoke the interpreter by specifying its pathname.

If you are on Linux, OS X or Cygwin, install flask and extensions by entering the following commands, one after another:

$ flask/bin/pip install flask
$ flask/bin/pip install flask-login
$ flask/bin/pip install flask-openid
$ flask/bin/pip install flask-mail
$ flask/bin/pip install flask-sqlalchemy
$ flask/bin/pip install sqlalchemy-migrate
$ flask/bin/pip install flask-whooshalchemy
$ flask/bin/pip install flask-wtf
$ flask/bin/pip install flask-babel
$ flask/bin/pip install guess_language
$ flask/bin/pip install flipflop
$ flask/bin/pip install coverage

If you are on Windows the commands are slightly different:

$ flask\Scripts\pip install flask
$ flask\Scripts\pip install flask-login
$ flask\Scripts\pip install flask-openid
$ flask\Scripts\pip install flask-mail
$ flask\Scripts\pip install flask-sqlalchemy
$ flask\Scripts\pip install sqlalchemy-migrate
$ flask\Scripts\pip install flask-whooshalchemy
$ flask\Scripts\pip install flask-wtf
$ flask\Scripts\pip install flask-babel
$ flask\Scripts\pip install guess_language
$ flask\Scripts\pip install flipflop
$ flask\Scripts\pip install coverage

These commands will download and install all the packages that we will use for our application.

"Hello, World" in Flask

You now have a flask sub-folder inside your microblog folder that is populated with a Python interpreter and the Flask framework and extensions that we will use for this application. Now it's time to write our first web application!

After you cd to the microblog folder, let's create the basic folder structure for our application:

$ mkdir app
$ mkdir app/static
$ mkdir app/templates
$ mkdir tmp

The app folder will be where we will put our application package. The static sub-folder is where we will store static files like images, javascripts, and cascading style sheets. The templates sub-folder is obviously where our templates will go.

Let's start by creating a simple init script for our app package (file app/__init__.py):

from flask import Flask

app = Flask(__name__)
from app import views

The script above simply creates the application object (of class Flask) and then imports the views module, which we haven't written yet. Do not confuse app the variable (which gets assigned the Flask instance) with app the package (from which we import the views module).

If you are wondering why the import statement is at the end and not at the beginning of the script as it is always done, the reason is to avoid circular references, because you are going to see that the views module needs to import the app variable defined in this script. Putting the import at the end avoids the circular import error.

The views are the handlers that respond to requests from web browsers or other clients. In Flask handlers are written as Python functions. Each view function is mapped to one or more request URLs.

Let's write our first view function (file app/views.py):

from app import app

@app.route('/')
@app.route('/index')
def index():
    return "Hello, World!"

This view is actually pretty simple, it just returns a string, to be displayed on the client's web browser. The two route decorators above the function create the mappings from URLs / and /index to this function.

The final step to have a fully working web application is to create a script that starts up the development web server with our application. Let's call this script run.py, and put it in the root folder:

#!flask/bin/python
from app import app
app.run(debug=True)

The script simply imports the app variable from our app package and invokes its run method to start the server. Remember that the app variable holds the Flask instance that we created it above.

To start the app you just run this script. On OS X, Linux and Cygwin you have to indicate that this is an executable file before you can run it:

$ chmod a+x run.py

Then the script can simply be executed as follows:

./run.py

On Windows the process is a bit different. There is no need to indicate the file is executable. Instead you have to run the script as an argument to the Python interpreter from the virtual environment:

$ flask\Scripts\python run.py

After the server initializes it will listen on port 5000 waiting for connections. Now open up your web browser and enter the following URL in the address field:

http://localhost:5000

Alternatively you can use the following URL:

http://localhost:5000/index

Do you see the route mappings in action? The first URL maps to /, while the second maps to /index. Both routes are associated with our view function, so they produce the same result. If you enter any other URL you will get an error, since only these two have been defined.

When you are done playing with the server you can just hit Ctrl-C to stop it.

And with this I conclude this first installment of this tutorial.

For those of you that are lazy typists, you can download the code from this tutorial below:

Download microblog-0.1.zip.

Note that you still need to install Flask as indicated above before you can run the application.

What's next

In the next part of the series we will modify our little application to use HTML templates.

I hope to see you in the next chapter.

Miguel

Become a Patron!

Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon!

350 comments
  • #101 Az Madujibeya said

    Hi Miguel,

    This set of tutorials is superb and I've just started going through them yesterday now that time permits.

    Instead of doing the pip installs one line at a time, which can lead to mistakes, why not put all the requirements into a file and execute them in one go:

    $ pip install - r requirments.txt

    where the contents of the requirement.txt would be:

    Flask==0.9
    flask-login
    flask-openid
    flask-mail
    sqlalchemy==0.7.10
    sqlalchemy-migrate
    flask-whooshalchemy
    flask-wtf
    flask-babel
    flup

    I had the same error with sqlalchemy-migrate and sqlalchemy incompatibility that was being reported so I simply recreated the entire structure from scratch in a new directory copying the relevant files as I went along. Using the requirements.txt saves a lot of time in this process plus it can be (should be) part of your git/svn commit so that other people can access it (at least in a proper project, but practice makes perfect right ;-) ).

    I'm looking forward to the Heroku section at the end as I recently was involved in a project that used Heroku for the first time so I'm keen to compare notes :-)

    Regards

    Az

  • #102 allen said

    @Miguel Grinberg, thanks for your article, it's a amazing beginning for me to learning flask.

  • #103 Cynthia said

    Hi Miguel. Great tutorial. I'm helping a couple people get this set up and am finding a couple problems with the pip installs. I can't reproduce it on my personal machine (using --no-site-packages with virtualenv and not using it) but in testing I did notice that when you pip install flask-sqlalchemy it clobbers flask==0.9 and automatically updates it to 0.10 without telling you. Once that happens, do I need to go back and pip uninstall and then install 0.9 again?

    In following the installs as is on other machines, the install of flask-whooshalchemy fails with the following error:

    Could not find a version that satisfies the requirement flask-whooshalchemy (from versions: 0.5a, 0.3a.macosx-10.6-x86_64, 0.2a, v0.52a, 0.1a, 0.54a, 0.4a, 0.53a, 0.51a, 0.55a)
    Cleaning up...
    No distributions matching the version for flask-whooshalchemy

    and installing flask-babel fails when trying to install pytz with a similar message about not being able to find a compatible version:

    Downloading/unpacking pytz (from flask-babel)
    Could not find a version that satisfies the requirement pytz (from flask-babel) (from versions: 2009r, 2008b, 2009f, 2008c, 2007g, 2011g, 2005m, 2011e, 2007f, 2011k, 2007k, 2006j, 2008h, 2008i, 2011e, 2008a, 2009e, 2006g, 2011j, 2010l, 2005m, 2008i, 2005k, 2008g, 2007c, 2007i, 2009l, 2009r, 2006j, 2011k, 2007d, 2006p, 2009i, 2009u, 2007i, 2009f, 2010g, 2008h, 2009a, 2007g, 2011e, 2006p, 2012b, 2010k, 2005r, 2007f, 2009l, 2009p, 2008c, 2009j, 2008g, 2010g, 2010h, 2011h, 2010k, 2007c, 2007d, 2011d, 2009l, 2011c, 2008a, 2005m, 2007k, 2009n, 2011d, 2010o, 2013b, 2012h, 2010e, 2012c, 2012d, 2012f, 2011n, 2011b, 2011j, 2008c, 2012j, 2007k, 2009f, 2009d, 2010e, 2010b, 2013b, 2011d, 2009p, 2008h, 2005r, 2009i, 2009n, 2009a, 2010k, 2008g, 2006g, 2008b, 2012c, 2009i, 2007g, 2012c, 2010h, 2011n, 2012g, 2007d, 2008a, 2009u, 2012g, 2010o, 2006p, 2010b, 2009u, 2012d, 2011k, 2012f, 2009a, 2007f, 2011h, 2010l, 2009j, 2011g, 2009g, 2009g, 2005r, 2011c, 2012g, 2009g, 2012d, 2009j, 2010o, 2007c, 2010g, 2006g, 2009d, 2010h, 2005k, 2006j, 2010b, 2009n, 2011g, 2011c, 2012b, 2009e, 2009d, 2011j, 2007i, 2012j, 2010l, 2009r, 2012h, 2010e, 2009p, 2008i, 2012f, 2009e, 2012b, 2011h, 2005k, 2008b, 2011n, 2012j, 2013b, 2004b)
    Cleaning up...
    No distributions matching the version for pytz (from flask-babel)

    Like I said, I can't reproduce the problem on my Mac, but two other macs are failing with those errors on install. Any thoughts?

    Thought you might like to know about the silent clobbering of flask 0.9 to flask 0.10, though.

    Thanks again.

  • #104 Miguel Grinberg said

    @Cynthia: instead of installing packages one by one you can try installing via the requirements.txt file, either one you generate from your working mac (pip freeze > requirements.txt) or the one in my github. The requirements file includes specific versions for all the packages.

  • #105 Cynthia said

    @Miguel: Thanks! I made a requirements.txt file on my working mac. Don't know why I didn't think of that. Mostly, I guess, the point I wanted to make was to let you know that even if you specify flask==0.9 as above in the Installing Flask section, when you finish the process as listed, you'll have flask 0.10 without it being obvious that that had happened. Thanks again for the great tutorial.

  • #106 Majid said

    Hi, I read the comments, lot of people asked the same question, I don't know how did they dealt about it :

    Abdelmajids-iMac:app majid$ ls
    init.py run.py static templates views.py
    Abdelmajids-iMac:app majid$ ./run.py
    -bash: ./run.py: flask/bin/python: bad interpreter: No such file or directory
    Abdelmajids-iMac:app majid$

    Thanks, your help is appreciated.

  • #107 Miguel Grinberg said

    @Majid: see in this article the instructions to set up a Python virtual environment. Also your files are not in the correct directories, see my project on github for reference.

  • #108 Taylor said

    I got this error when running:
    flask\Scripts\pip install sqlalchemy-migrate

    (ENV)unknowne4ce8f0731ca:ENV taylorbarnett$ flask\Scripts\pip install sqlalchemy-migrate
    -bash: flaskScriptspip: command not found

    I went ahead and skipped that command. Is there any fix for this?

  • #109 Miguel Grinberg said

    @Taylor: you are using the Windows command for installing. It seems you are using bash, so you need to use "flask/bin/pip install sqlalchemy-migrate" instead.

  • #110 PJ said

    Thanks for this tutorial, great resource.
    Small problem with the windows install instructions, the line:
    flask/bin/pip install sqlalchemy==0.7.9
    Should be:
    flask\Scripts\pip install sqlalchemy==0.7.9

    Thanks
    PJ

  • #111 Anders said

    Hello. Looks like you need to add
    ==0.8.4 at the end of flask\Scripts\pip install flask-wtf to get past part 3 of the guide.

  • #112 Stéphan said

    Hi Miguel!
    First thanks for this very valuable tutorial. I've been studying every step up to i18n/l10n and now I'm facing problems and am digging for a solution.
    When I run "my" code or yours from microblog-0.14.zip, I got two problems.

    Keep up the good work !

  • #113 crash said

    Hi..new here to python. just curious. I ran the app on port 5000 as mentioned here. Then, I telnet to the ip with port 5000. Without breaking the telnet, then i point my browser over to port 5000. Browser keeps loading without anything. Immediately when i terminated the telnet, the browser sees Hello World. Is the flask server supporting only serial process ?

  • #114 Haria said

    As of Flask 0.9.0, the import statements in app/forms.py must be modified from:
    from flask.ext.wtf import Form, TextField, BooleanField
    from flask.ext.wtf import Required
    And changed to:
    from flask.ext.wtf import Form
    from wtforms import TextField, BooleanField
    from wtforms.validators import Required

  • #115 Miguel Grinberg said

    @crash: you are using the development web server, which by default runs a single thread. Note that this is not a production web server, it is only good for development.

  • #116 B Donn said

    I just ran this command at the beginning of the tutorial and I'm already stuck.
    flask/bin/pip install flask==0.9
    flask/bin/pip install flask-login
    Terminal is filling up with a bunch of messages that say these folders do not exist. Any suggestions? Complete beginner here by the way.

  • #117 Miguel Grinberg said

    @B: Did you create a virtual environment before running pip?

  • #118 BDonn said

    Um, I'm not sure. I followed the steps below. Maybe I did something wrong. Do I need to create a separate folder called flask? What should the folder be called that I am putting virtualenv.py into?

    "Next, download virtualenv.py and put it inside the new folder.

    To create the virtual environment enter the following command:

    python virtualenv.py flask"

    Also, what exactly is "python virtualenv.py flask" doing? What does the flask part mean exactly at the end, is that just specifying the folder?

  • #119 Miguel Grinberg said

    "python virtualenv.py flask" creates a virtual environment called flask. Google "python virtualenv" to find the documentation for this tool. If you skipped that step then pretty much everything else you do will fail.

  • #120 Eko Wibowo said

    Very concise! I am hoping to be able create a working Web API using Flask by following this tutorial
    Thanks so much!

  • #121 Vinod Louis said

    hi,
    I was following the installation procedures as mentioned by you. i'm using python 3.3.2 on windows platform till

    python virtualenv.py flask

    command all goes fine but as soon as i run

    pip install flask==0.9

    it gives me this error

    Downloading/unpacking flask==0.9
    Downloading Flask-0.9.tar.gz (481kB): 481kB downloaded
    Running setup.py egg_info for package flask
    Traceback (most recent call last):
    File "<string>", line 16, in <module>
    File "D:\Technologies\flaskpython\flask\build\flask\setup.py", line 62
    print "Audit requires PyFlakes installed in your system."
    ^
    SyntaxError: invalid syntax
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

    File "<string>", line 16, in <module>

    File "D:\Technologies\flaskpython\flask\build\flask\setup.py", line 62

    print "Audit requires PyFlakes installed in your system."

                                                        ^
    

    SyntaxError: invalid syntax

    <hr />

    Cleaning up...
    Command python setup.py egg_info failed with error code 1 in D:\Technologies\fla
    skpython\flask\build\flask
    Storing complete log in C:\Users\wa\pip\pip.log

  • #122 Miguel Grinberg said

    @Vinod: Flask 0.9 does not work on Python 3, you have to use Python 2.7.

  • #123 Glen Baker said

    Thanks for this great tutorial, Miguel! I ran through all of these and really appreciate your direct teaching style. Really quality work :)

  • #124 scott robinett said

    trying to install the flask on the beagleboard black (Ubuntu 13.04, Python 2.7.4) and the vitualenv is failing with error code 1. Kind of new to this and can't figure out what the issue is. any suggestions? thanks, great tutorial.

  • #125 Miguel Grinberg said

    @scott: can you show me the output you get when you run the command?