2012-05-07T06:05:40Z

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.

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

350 comments

  • #176 Miguel Grinberg said 2014-01-22T15:14:12Z

    @Ann: how are you running run.py? You should be running this command: $ flask/bin/python run.py

  • #177 James Nicholson said 2014-01-26T03:42:47Z

    I believe there's a typo in the 'Install Flask' section within the Linux extensions area.

    Currently reads: flask/bin/pip install flask-sqlalchemy==0.16

    Should read: flask/bin/pip install flask-sqlalchemy==0.1.6

    I received the below error: No distributions matching the version for sqlalchemy==0.16

    Thanks for the great tutorial, I look forward to your book!

  • #178 Miguel Grinberg said 2014-01-27T19:51:32Z

    @James: there is a version 0.16 of Flask-SQLAlchemy: https://pypi.python.org/pypi/Flask-SQLAlchemy/0.16

  • #179 jda2000 said 2014-01-31T07:26:10Z

    If you are on a Raspberry Pi and aren't running a GUI or web browser on the box, you might want to have "app.run(host='0.0.0.0', debug = True)" as the last line of run.py. That way, you can browse in from another PC on your lan.

    You can use the "ip address show" command on the Pi to figure out what to put instead of "localhost" in the URL. You'd be looking for a line that looked like: "inet 192.168.0.5"... The URL then would be http://192.168.0.5:5000

    If you have avahi installed on the Raspberry Pi and have not changed the hostname it would just be http://raspberrypi.local:5000

    That's all assuming you are running raspbian.

  • #180 jda2000 said 2014-02-01T22:03:04Z

    Hey Miguel, This might be a good place to note that

    app.run(host='0.0.0.0', debug=True)

    can be used to allow testing with browsers running on other systems on the lan. This can be especially useful for Raspberry Pi owners who probably have faster browsers on a PC mac or tablet.

  • #181 SaiGo said 2014-02-03T13:23:49Z

    in run.py the code '#!flask/bin/python' did not work for me. Instead I had to use '#!/usr/bin/env python'. What is the difference? Why does first instance not work, and the second attempt work?

    Sai

  • #182 Victor said 2014-02-05T02:34:01Z

    Hi, This is really great! I'm just starting, but can I download the application files somewhere? I'm having trouble following the folder/file structure. Thanks!

    ~Victor

  • #183 Garv said 2014-02-28T12:25:39Z

    hey hi i have placed the folders in the right place. when i run this command in windows 8 flask/Scripts/python run .py after cd microblog it says 'flask' is not recognized as in internal external command. whats wrong??

  • #184 Miguel Grinberg said 2014-02-28T15:08:39Z

    @Garv: you need to use backslashes, not forward slashes. It's flask\Scripts\python run.py.

  • #185 zigs said 2014-03-06T07:17:02Z

    Hi this is a good tutorial. I would like to suggest correctness in line for run server in windows flask/Scripts/python run.py this should be flask\Scripts\python run.py Thanks.

  • #186 Nicolas Joannin said 2014-03-13T08:33:38Z

    Hi Miguel, This looks really interesting, and I'm tempted by the book... However, I code in Python 3. Does the book cover it or is it just Python 2.x? Cheers, Nicolas

  • #187 Miguel Grinberg said 2014-03-13T16:11:47Z

    @Nicolas: These tutorials work on Python 2 only, Flask did not support Python 3 back when I wrote them. The book is valid for Python 2.7 and Python 3.3+, all the examples from the book run on both.

  • #188 Fraser Gorrie said 2014-03-20T15:11:48Z

    Hi Miguel,

    Excellent tutorial series. So nice to see a fully worked out example as it progressed.

    I am going through the first steps and running "python virtualenv.py flask" with the latest version 1.11.4 of virtualenv.py . However, it breaks with "pip not found".

    Do you have a strategy yourself of dealing with tutorial instructions that reference tools that have been updated since the tutorial was written?

    Fraser

  • #189 Aaron said 2014-03-20T18:08:35Z

    Ok, I've gone through this page at least 5 times, done everything exactly as typed, and even corrected the line #!flask/bin/python to !#/usr/bin/env python because the former throws an error "bad interpreter"

    However, this app, as of the writing on this page, simply does not launch, failing with an error:

    File 'run.py', line 2, in from app import app ImportError: No module named app

    My files are verbatim like yours (checked against download), except the later files like setup.py. I used the virtualenv.py script, installed the extensions just as you did, to the local site-packages folder, not the system one, and ran against the local python interpreter, same error, or the 'bad interpreter' one. Not running an active virtualenv, just using the direct paths to python, pip, and flask.

    I'm on a Mac, 10.8.5, and have run through, likely, a 100+ intro tutorials on a dozen different languages, so there's something not working right here. Plz hlp.

  • #190 Aaron said 2014-03-20T18:48:41Z

    Update: I didn't see this part;

    "…Let's call this script run.py, and put it in the root folder:"

    Ah, run.py file HAS to be in the /microblog folder (root), not /app, which is where mine was. Also, I changed the shebang back to what you have, "!#flask/bin/python" and now it does indeed work. So, apparently, like you probably assumed, the fault was on my end.

    The tiniest mistakes can cause so much frustration, endless Googling, and wasting an entire morning. Yikes.

  • #191 Miguel Grinberg said 2014-03-21T15:50:46Z

    @Fraser: I'm certain that pip is still installed when you make a virtualenv. Make sure you either activate the virtualenv or else you call it with its path, as "flask/bin/pip" as I show above.

  • #192 Miguel Grinberg said 2014-03-21T15:52:05Z

    @Aaron: sorry you wasted so much time on this. If it happens again, you can compare your project with mine on github: https://github.com/miguelgrinberg/microblog.

  • #193 Ilya said 2014-03-22T15:32:34Z

    Hi Miguel, thanks a lot for the great tutorial, already looking forward to the book. I am still wondering whether circular imports are really necessary ( Why do you import views in init.py ?) and why you dont use relative imports (from . import app in views.py) which seems more robust?

  • #194 Miguel Grinberg said 2014-03-22T18:26:39Z

    @Ilya: views needs to be imported so that the routes contained in it are registered with the application.

    Regarding relative imports, I agree with you 100%, that is how I do it these days. This article was written two years ago. See my newer projects on github, I have improved the project organization quite a bit. A good example is the project featured in my book, "flasky".

  • #195 Adam said 2014-03-24T09:21:50Z

    Hi. Great tutorial. It's just what I needed since i'm completely new to the whole web api-scene in general and need a fairly basic tutorial. Anyway; when I try "./run.py" I get the following error: "./run.py: flask/bin/python: bad interpreter: No such file or directory" I am using virtualenv, and my folders are laid out: /app /apiMain.py (equivelant to your views.py) /templates /index.html /init.py /ENV(virtual enviroment) /run.py

    I'm guessing it's to with me using a virtualenv?

  • #196 Miguel Grinberg said 2014-03-25T04:49:36Z

    @Adam: you need to change the path to the python interpreter in the first line of run.py. I use "flask" as the name of my virtual environment, you are using ENV.

  • #197 C. T. Grant said 2014-04-04T21:47:09Z

    Miguel, I've been curious about Flask. So far, this seem like a perfect introduction. Thanks for putting it up, and I'm looking forward to the rest.

  • #198 David said 2014-04-15T15:21:37Z

    I began this tutorial on my laptop, but would like to switch to my desktop; what is the best way to clone the virtual environment? All files are in a repo on github. The problem I am encountering is as follows: 1. repo is cloned onto desktop (windows 8.1 64) 2. activated virtualenv using flask\Scripts\activate.py 3. If I try running run.py, I get ImportError: No module named site

    Thoughts?

  • #199 Miguel Grinberg said 2014-04-16T05:51:12Z

    @David: why don't you make a new virtual environment? Follow the steps in this article to install all the required packages.

  • #200 klz said 2014-04-20T11:25:22Z

    Good tutorial, but ever since I started fresh and installed the virtual environment I've been having problems. I'm running: ".../tournament>run.py" from the core directory and I get this:

    Traceback (most recent call last): File "C:\Users\user\Desktop\tournament\run.py", line 2, in from app import app File "C:\Users\user\Desktop\tournament\app__init__.py", line 2, in from app import views File "C:\Users\user\Desktop\tournament\app\views.py", line 3, in from forms import LoginForm ImportError: No module named 'forms'

    If I use ".../tournament>python run.py" instead I receive this:

    Traceback (most recent call last): File "run.py", line 2, in from app import app File "C:\Users\user\Desktop\tournament\app__init__.py", line 1, in from flask import Flask ImportError: cannot import name 'Flask'

    I'm using Python 3.4, Windows 7, 64-bit. I'm not following your tutorial to the letter, but here's my directories:

    tournament/ run.py config.py app/ init.py views.py forms.py static/ ... templates/ ... flask/ Lib/ ... Scripts/ ... Include/ ... tmp/