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
  • #301 Carlos Lomeli said

    Thank you very much for this tutorial!. I have a situation that do not understand.
    My code works for
    python run.py

    but not for
    ./run.py

    when a try the second one, gives this error
    Traceback (most recent call last):
    File "run.py", line 2, in <module>
    from app import app
    File "/home/lomelisan/Documentos/microblog/app/init.py", line 1, in <module>
    from flask import Flask
    ImportError: No module named flask

  • #302 Ashish Rathi said

    Hi Miguel,
    Great Tutorial!!

    Though I am a bit confused about the usage of "app" variable and the "app" package.
    Why do "package" and "variable" have the same value "app"??

  • #303 Miguel Grinberg said

    @Carlos: you need to change the shebang line in run.py (first line in the script) to include the path to the python interpreter in your virtualenv.

  • #304 Miguel Grinberg said

    @Ashish: sorry about that, you are the second person who complains that the use of "app" for both the package and the variable is confusing. No good reason, the "app" package contains the application code, including the "app" variable which represents the WSGI application.

  • #305 Carlos said

    Miguel thank you for your quickly response, I'm sorry for that mistake it was just a type error in the run.py file. I have to thank you again for let us know that flask in "from flask import Flask" is the module and not the folder like app.

  • #306 Beliar said

    Nice tutorial.

    I'm still deciding what framework I'm going to use for my project but I'm leaning towards Flask.

    I don't understand however, why the book for Kindle costs 11USD, for Nook 19, and the PDF 34. I'm assuming it's not possible to buy the Kindle one and read it on a PC, right? That is so unfair... I could buy the paperback one because I don't have these eBook readers and I rather read it on paper than on PC screen, so the extra money is worth imho, however, I simply can't do that because the customhouse in my country is so ridiculously slow that by the time it arrives Flask 1.0 would be rolled out and bugfixed already (seriously, packages may take years to arrive). I know these values are low for the US, but 34USD is like 15% of my monthly wage so consider that before criticizing my tight-fist please.

    Thank you.

  • #307 Miguel Grinberg said

    @Beliar: unfortunately you are complaining to the wrong person. I wrote the book, but the publisher (O'Reilly) is the one that sells it, and stores such as Amazon/B&N/etc negotiate prices with O'Reilly, so really I have no say in the matter. What I can tell you though, is that there is a free kindle app for PC, so you could buy the Kindle version and read it on your computer.

  • #308 Beliar said

    @Miguel: Thank you for your quick reply. I didn't know it's possible to buy and read Kindle books on a PC (I'm assuming it's also possible(/legal) to print some contents for personal use). That's awesome, especially considering the accessible prices! Thank you! :)

    PS: I hope they revert a fair share to you ;).

  • #309 Vasiliy Toporov said

    If you are using virtualenvwrapper on Ubuntu for this tutorial, you need to change the first line of /microblog/run.py to right python interpreter path.
    For example, you created your env like:

    mkvirtualenv --python=/usr/bin/python3 flask-mega-tutorial

    Then activated it:

    workon flask-mega-tutorial

    Than install all the packages via pip.

    If you write something like "#!/usr/bin/python3" in run.py you should notice that
    system-wide python knows nothing about flask package (isolation, right?). So,
    you need to place the link to python, that is using by your environment:

    <h1>!/home/your_system_user_name/.virtualenvs/flask-mega-tutorial/bin/python</h1>
  • #310 Mahesh said

    i'm getting error as

    from: can't read /var/mail/app
    ./run.py: line 2: syntax error near unexpected token debug=True' ./run.py: line 2:app.run(debug=True)'

  • #311 Miguel Grinberg said

    @Mahesh: try running "python app.py".

  • #312 darshan said

    Hii, I'm also new to web in python. I have followed your instruction but i'm getting error while executing this - python -m venv flask. I have installed virtualenv library properly. I'm working on widows Platform.
    Thanks in Advance.

  • #313 Garrin said

    Note:

    When I am in the microblog main directory, the line:

    <h1>!flask-tutorial-microblog/bin/python</h1>

    (That's how I named the venv)
    Doesn't make sense, because I already am in the venv directory, and don't need to go into yet another folder named after my venv. When I changed it to only:

    <h1>!bin/python</h1>

    I could then use "./run.py" to start the server, while I had the following error, when I have the additional directory name in front:
    bash: ./run.py: flask-tutorial-microblog/bin/python: bad interpreter: No such file or directory

  • #314 Miguel Grinberg said

    @darshan: if you are using Python 2.7, the command is "virtualenv flask".

  • #315 Miguel Grinberg said

    @Garrin: the application does not go inside the virtual environment directory, it goes outside, in the parent directory. This is how the project should be structured:

    flask-tutorial-microblog\
    run.py
    <other application files and sub-directories>
    flask\
    bin\
    python

  • #316 Lakshmi Narayana Ambarkar said

    A first step, very nicely described. One feedback: I have been looking for a button/link to the next chapter. When you get some time, please add the Next and Previous links.

  • #317 Natanael Souza said

    May you explain why "$ flask\Scripts\pip install package" does not works as before? Now I have to type "python -m pip install XXX "

  • #318 Miguel Grinberg said

    @Natanael: what error do you get?

  • #319 Natanael Souza said

    The error is that: Fatal error in launcher: Unable to create process using '"C:\Users\Natanael\flas
    k\Scripts\python.exe" "C:\Users\Natanael\microblog\flask\Scripts\pip.exe" sqlalchemy-migrate'

    I am following well the tutorial, its just a little doubt, thx!

  • #320 Miguel Grinberg said

    @Natanael: if you google this error you will find that most people get this when they have Python installed on a path that has spaces. Is that your case?

  • #321 Manish said

    Hi Miguel,

    First of all I want to say massive thank you for such dedication and amazing follow up you are doing on the comments section. I followed all the instructions (I am using windows 7). But when I try to run the run.py from the virtual enviornment it says cant open the file as there is no such file in the directory.

    According to your instructions I have created run.py and placed it in microblog root folder. The virtual env is created in flask folder. So on the command line my path looks like microblog\flask\scripts python run.py

    Any help would be appreciated.

    Many thanks,
    Manish

  • #322 Miguel Grinberg said

    @Manish: Try this:

    microblog\flask\Scripts\python run.py

    Note that python is part of the command, it does not go separated from it.

  • #323 Natanael Souza said

    @Miguel Grinberg

    Yes, it was that, the problem was in path. Thx for your help and sorry for my bad english!

  • #324 Michael E. Rose said

    Dear Miguel,
    I tried to make an .exe out of my flask-script. Building with py2exe, where I add the option to include flask and flask-WTF. While building, I get an ImportError: no module named flask-WTF. Building with the option to include flask only, I manage to build, but the .exe complains with another ImportError: no module named flask.ext.wtf.
    Do you know why this is?
    Michael

  • #325 Miguel Grinberg said

    @Michael: I suspect the "flask.ext.whatever" style of importing Flask extensions is confusing py2exe. Try changing all those imports to "flask_whatever" in your code, that will likely work fine, and is in fact the recommended way to import in the upcoming Flask 1.0 release.