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
  • #276 Bruno said

    Hi Miguel,
    Looks like there is no way to search the forum for an answer to my problem, so excuse me if you already covered it.
    I'm on OSX, and Safari (or Chrome) can't open the page localhost:5000 because it "can't connect to server localhost." Any idea ?
    Happy holidays,
    Bruno

  • #277 Miguel Grinberg said

    @Bruno: That means that you are not running the Flask server. Did you execute the "run.py" script as shown above?

  • #278 Noel said

    Thanks for a great article. I can't seem to call python from my cmd although I installed the python 3.4 exe.

  • #279 Miguel Grinberg said

    @Noel: it's probably not in your PATH. See https://docs.python.org/3/using/windows.html?highlight=windows#finding-the-python-executable for help locating the Python binary.

  • #280 lalitha said

    hi i'm new to python and i'm to instal python in virtual environment.and i'm unable to understand how to implement flask please help out of this......

  • #281 Seven Hong said

    Hi Miguel, first of all thank you for this excellent tutorial!

    I want to know, in app/init.py, why do I need to put this line:

    from app import view

    I actually removed this line and I found the server doesn't response to '/' and '/index' routes anymore. What I am confused about this, is that I thought these two routes (/ and /index) are already mapped when I wrote the app.route decorator in app/views.py.

  • #282 Miguel Grinberg said

    @Seven: what the import does is trigger all those app.route decorators to run. These register all the routes with the Flask application instance. This can be confusing, because we don't really need the functions, just need the decorators to execute.

  • #283 Greg said

    Thanks for the tutorial but, for ease of use, wouldn't it be more clear if the variable "app" had a different name so as not to confuse it with both the package of the same name?

  • #284 Miguel Grinberg said

    Greg: it is interesting that only recently (almost 3 years after I published this article) I hear about people getting confused with the two "apps". I'm not going to make a change, mainly because regardless of which one of the two I change, the entire tutorial will be affected, I will have to revise the 18 versions of code (relatively easy because I can test) and the 18 tutorials (harder because it isn't testable code).

    If I had to do it, my preference would be to change the "app" package, maybe to "microblog", and leave "app" for the Flask instance.

  • #285 Aaron Deadman said

    Since SQLAlchemy-migrate is no longer supported, and we should use Flask-migrate with the database in a later chapter, the init.py and run.py files need a small change to support the Manager:

    app/init.py:
    from flask import Flask
    from flask.ext import Manager
    app = Flask(name)
    from app import views
    if name=='main':
    manager.run()

    and run.py:

    <h1>!flask/bin/python</h1>

    from app import app, manager
    app.debug=True
    manager.run()

  • #286 Miguel Grinberg said

    @Aaron: sqlalchemy-migrate continues to be supported. It changed ownership a while back, but it is still alive. Note that I do not use Flask-Migrate in this tutorial, so adding Flask-Script is not necessary for this application, unless you want to convert it to Flask-Migrate yourself.

  • #287 floydberg said

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

    let's you access the development server from another computer on the network

    http://stackoverflow.com/questions/7023052/flask-configure-dev-server-to-be-visible-across-the-network

  • #288 Anmol Seth said

    Hi Miguel, I was trying to use this tutorial in slightly different way.
    i made a virtual environment and activated it
    but when i try to to run it i get error

    COMMAND = #!flask/bin/python
    from app import app

    ERROR = from: can't read /var/mail/app

    Please help.

  • #289 Miguel Grinberg said

    @Anmol: the shebang line in your script (first line) is probably incorrect. Try running the script as "python run.py" instead of "./run.py".

  • #290 George said

    Thank you for your great work on this tutorial!!! It 's worthy of donation!

  • #291 Bruce said

    Nice tutorial but as you might guess I've got a problem. (Windows Vista) Trying to connect over localhost I keep getting code 400, Bad request syntax. This is echoing on the command prompt. On the Firefox browser I get SSL received a record that exceeded the maximum permissible length. (Error code: ssl_error_rx_record_too_long). Should this be secure shell?

  • #292 Idris said

    Can you explain the shebang line '#!flask/bin/python' in run.py. I've never seen anything like that and it doesn't work for me. I replaced it with a `#!/usr/bin/env python' on OSX and it worked, so I'm curious if your shebang is in an error or something to learn. Thanks!

  • #293 peter said

    hi all,
    there is a bug affecting the set up of the virtual environment on ubuntu trusty. that is, although python 3.4 is installed with trusty, "python -m venv flask" will fail for a missing "ensurepip" module. see "https://bugs.launchpad.net/ubuntu/+source/python3.4/+bug/1290847" for a detailed discussion. the workaround proposed (and working for me so far) is to: "sudo apt-get install python-virtualenv" and "virtualenv flask -p python3". thanks for the tutorial. regards, peter

  • #294 Miguel Grinberg said

    @Bruce: I really don't know. I know that this tutorial can be done on Windows 7 or 8, but don't have access to a Vista machine. I recommend that you either upgrade Windows, or else install a Linux VM using VirtualBox.

  • #295 Miguel Grinberg said

    @Idris: that shebang line depends on having a virtual environment named flask in your project directory. It basically references the python interpreter from the virtual environment directly, so you don't have to activate the environment. What you changed it to is fine, you can activate the environment and then that will work in the same way.

  • #296 Ted Krum said

    Miguel, you have inspired me to use flask! Following your lead in your excellent new book, I'm trying to use Flask together with virtualenv.
    Sadly, I ran into a small problem when I had to import the phone numbers.py library, which is not installed using pip. Here's the background:

    I'm trying to build a simple API server using Flask that will validate and store international phone numbers using this library. I previously installed Flask and several Flask extensions in a virtualenv, and started building my app. So far so good. But after downloading and installing phone numbers.py using its own installer, I found that python running inside virtualenv could no longer find my app script! Looking at the directory, it's sitting right there, but python does not recognize it any more. The only other wrinkle I can think of is that after doing the install, I used an external text editor (outside the venv) to edit my app script and re-save it.

    What have I done wrong?

    I compared my environment variables inside and outside virtualenv. They are the same except for the following 3 additions:

    VIRTUAL_ENV=/Users/tokrum/callcenter/venv
    PATH=/Users/tokrum/callcenter/venv/bin: …(was added to my $PATH, but the rest of pre-existing PATH as before….)
    PS1=(venv)\h:\W \u\$

    My app is called call center-v0-1.py. It lives in a directory called 'callcenter', along with the phone numbers-7.0.1 and venv folders at the same level of my directory structure.

    Thanks for any light you can shed on this.

    Thanks,
    Ted Krum

  • #297 Miguel Grinberg said

    @Ted: How did you install this library, and why can't you just do "pip install phonenumbers" to install it into the virtualenv?

  • #298 CJ said

    So, I ran into an error that I saw a lot of people here getting.

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

    because I couldn't import the models.

    I would get something like

    flask/bin/pip3: "path: bad interpreter: No such file or directory

    For some reason, python doesn't play well with Google Drive. I tried the above steps in Documents, and it worked fine!

    (On a Mac)

    Hope this helped someone.

  • #299 jasmin bhambure said

    Im using python3.4 and create microblog folder but facing difficulty in this command python -m venv flask
    C:\Python34\microblog>python -m venv flask
    'python' is not recognized as an internal or external command,
    operable program or batch file.

  • #300 Miguel Grinberg said

    @jasmin: you don't have your python interpreter in your path. Try using the full path to your python interpreter:

    C:\Python34\microblog>C:\Python34\python -m venv flask