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

(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.


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

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:

from app import app

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:


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:


Alternatively you can use the following URL:


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.



  • #76 Hemanth Hemszz said 2013-05-21T05:37:06Z

    Learnt it very very easily........ thnks a lot

  • #77 kim said 2013-05-24T08:39:40Z

    it works.Thanks, I am a novice application developers. I will continue to learn, your article fantastic.

  • #78 Jade said 2013-05-29T22:17:37Z

    Hi Miguel, your information is wonderful. I made it work.

    I do have one question. I like to use windows clipboard. I installed the windows extension pywin32-218.win32-py2.6.exe. it only allows me to install to my main python which is under c:\python26. after install the extension, I ran virtualenv.py to create a virtual environment. But when I do from win32clipboard import * in my code, I got error complaining no such model. Do you know how to set it up correctly? Thanks!

  • #79 Miguel Grinberg said 2013-05-29T23:47:27Z

    @Jade: try adding option --system-site-packages to virtualenv.py when you create the virtual environment. If that doesn't work, the following stackoverflow question has a few ideas on how to install pywin32 on a virtualenv: http://stackoverflow.com/questions/1830304/how-can-i-use-pywin32-with-a-virtualenv-without-having-to-include-the-host-envir

  • #80 Brent said 2013-06-13T17:53:26Z

    Howdy there!

    Such a great tutorial and I'm still working through it (slowly but surely!). I did have one question:

    I can run easily the webserver (via ./run.py) from my local machine, but if I try follow the steps on a different machine (say one that I've ssh'd into), I have no idea how to access http://localhost:5000 on that machine. I mean, I can put a dummy index.html file there and use a url to that file, but how do I access the webserver? Any help will be greatly appreciated!

  • #81 Miguel Grinberg said 2013-06-14T02:33:30Z

    To access the server from another computer you have to change the run.py script a bit. Instead of saying app.run(debug = True) you need to say app.run(host = '', debug = True). This configures the server to listen on the public interface. You also need to make sure your firewall does not block port 5000, or add a port = N to the app.run statement with a port that is open.

  • #82 Brent said 2013-06-14T15:50:37Z


    Thanks for the quick reply! One last question. If I run it, what url should I use to access the reltant website? It's located in a subdirectory and here's an example of what I would use if it was an index.html file:


    For a webserver, what would this look like? Thanks in advance!

  • #83 Miguel Grinberg said 2013-06-14T17:00:45Z

    @Brent: web servers have the concept of "root" folder. Everything is relative to this root folder, so the physical directory structure of your project does not matter. When you use two machines you'll start the server in one and then in the other you will access http:///

  • #84 Sasha said 2013-06-15T22:12:38Z

    Hi Miguel Thank you for great tutorial!

  • #85 Randy said 2013-06-17T17:23:55Z

    Thanks for the detailed tutorial! When I got to the Part V, I ran into a problem with the newer versions of Flask and Flask-Login, as described here: http://stackoverflow.com/questions/17092849/flask-login-typeerror-decoding-unicode-is-not-supported . The solution listed also seemed to work for me. This is just FYI.

  • #86 Paul H said 2013-06-18T06:55:44Z

    Very, very nice Miguel,

    I think this kind of small (in scope) - but very complete (in tooling) - projects are the best way to get in touch with new technology.

  • #87 Nigel Borrill said 2013-06-18T13:16:30Z

    I have a problem early on in this. flask/bin/pip install flask-login Downloading/unpacking flask-login User for bitbucket.org:

    I guess this is recent as none of the comments 8 months ago mention having to enter a bitbucket user ?

  • #88 Nigel Borrill said 2013-06-18T13:18:23Z

    Oops sorry, just tried hitting CR a couple of times and it seems to have installed !

  • #89 Tian said 2013-06-19T03:24:48Z

    when I try to install sqlalchemy 0.7.9, it tells me this: $ flask/bin/pip install flask-sqlalchemy==0.7.9 Downloading/unpacking flask-sqlalchemy==0.7.9 Could not find a version that satisfies the requirement flask-sqlalchemy==0.7.9 (from versions: 0.11, 0.5, 0.6, 0.10, 0.12, 0.13, 0.9.1, 0.9, 0.15, 0.14, 0.16, dev, dev) No distributions matching the version for flask-sqlalchemy==0.7.9 Storing complete log in /Users/Tian/.pip/pip.log

    Could you please help me? Thank you!

  • #90 Miguel Grinberg said 2013-06-19T04:03:16Z

    @Tian: it's sqlalchemy that needs 0.7.9, not flask-sqlalchemy.

  • #91 Scotty said 2013-06-21T00:48:40Z

    Thanks a bunch for this tut, i'm stoked to go through it.

    A quick question:

    During sqlalchemy install, i get the following error... is it a problem?:

    Unable to find vcvarsall.bat WARNING: The C extension could not be compiled, speedups are not enabled. Failure information, if any, is above. Retrying the build without the C extension now.

    warning: no files found matching '*.jpg' under directory 'doc' no previously-included directories found matching 'doc\build\output'

    WARNING: The C extension could not be compiled, speedups are not enabled. Plain-Python build succeeded.


  • #92 Miguel Grinberg said 2013-06-21T01:42:40Z

    @Scotty: The MySQL extension can run from C code or from Python code. The C code version is faster, but it requires a C compiler to be installed. This message is saying that the Python version will be used, due to not finding a suitable C compiler in your system. On Windows most people have it setup like this, so I wouldn't worry about it unless you need the optimized driver.

  • #93 Niels said 2013-06-28T09:34:52Z

    Fantastic blog, and very nice explanations of installing. Thanks a lot!!!

  • #94 denis said 2013-07-01T20:34:32Z

    I discovered flask a few days ago, and now your great mega-tutorial. Is there a way to get all the articles in one pdf ? Regards.


  • #95 Miguel Grinberg said 2013-07-02T07:06:26Z

    @denis: No, sorry, I do not have a PDF version readily available.

  • #96 Jose Sapir said 2013-07-03T19:31:38Z

    Hi there. Thanks for the great tutorial!

    I'm having a problem with ./run.py. I get the following error:

    -bash: ./run.py: flask/bin/python: bad interpreter: No such file or directory

    The folder hierarchy is right and the scripts are cmd + c, cmd + v.

    Any ideas? Thanks

  • #97 Jose Sapir said 2013-07-03T19:35:41Z

    Oh, and when I run it with python run.py instead of with ./run.py I get:

    File "run.py", line 2, in from app import app File "/Users/JoseSapir/Documents/Python/microblog/flask/app/init.py", line 1, in from flask import Flask ImportError: No module named flask

  • #98 Miguel Grinberg said 2013-07-03T21:04:19Z

    @Jose: did you setup a virtualenv, as described above?

  • #99 Rohit Mohan said 2013-07-18T02:12:34Z

    Awesome series of articles, thank you! I've been looking for something like this for a long time now.

    I started off with the Hello World example (on Win7), setting up and everything, and I got everything to work, but I have a couple of questions.

    One, I wasn't able to install flask-whooshalchemy, flask-wtf or flask-babel. For all these, I got an error message from pip saying:

    Could not find any downloads that satisfy the requirement flash-wtf (or whatever else it couldn't find). What's going on?

    Second, in my virtual environment, there's a flask directory (created by calling python virtualenv flask), but it's not a Python package (it has no init.py). How, then, was Python able to import from it when it encountered:

    from flask import Flask

    in app/init.py?

    Thank you again!

  • #100 Miguel Grinberg said 2013-07-18T04:09:55Z

    @Rohit: What version of Flask are you using? Trying installing Flask 0.9 if you are currently running 0.10. The 0.10 release is very new, some extensions haven't been updated. I know for certain that Flask-Babel does not work well with Flask 0.10. For your second question you are confusing the name of the folder that is the root of the virtual environment with a Python package. The top "flask" folder is just a folder, if you look inside you will see there is a "lib" folder, and a few sub-folders inside it are the installed packages, including a package named "flask".