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:
- Part I: Hello, World! (this article)
- Part II: Templates
- Part III: Web Forms
- Part IV: Database
- Part V: User Logins
- Part VI: Profile Page And Avatars
- Part VII: Unit Testing
- Part VIII: Followers, Contacts And Friends
- Part IX: Pagination
- Part X: Full Text Search
- Part XI: Email Support
- Part XII: Facelift
- Part XIII: Dates and Times
- Part XIV: I18n and L10n
- Part XV: Ajax
- Part XVI: Debugging, Testing and Profiling
- Part XVII: Deployment on Linux (even on the Raspberry Pi!)
- Part XVIII: Deployment on the Heroku Cloud
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 installs
virtualenv`:
$ 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
-
#126 Sergey said
Please, add some file uploader to your tutorial please :)
-
#128 Miguel Grinberg said
@Valentin: you probably have the application package in a different location. I recommend that you download my version (link near the bottom of the article) and compare that against your version to find what's wrong.
-
#129 Tania said
Hello. I am on windows and I am using pip for the first time.I am not able to install any packages using pip, whenever i try something say "pip install <anypackage>", It gives me out the error "Cannot fetch index base URL https://pypi.python.org/simple/". I googled it but unable to find any working solution. Please help me.
-
#130 Miguel Grinberg said
@Tania: it could be a connection problem. make sure you can connect to pypi.python.org on your browser. I guess it could also have been a temporary problem on their side, give it another try and hopefully it will work.
-
#131 Tania said
It magically worked this morning and I guess It WAS a connection problem as you hinted. (I was able to connect to all other sites but pypi.python.org).Have resumed working through the tutorial. Thank you so much for replying. I am eagerly waiting for the book!! By the way, I know only the basics of python(started coding in Python a month ago). Will that hinder in my learning of Flask? Do i need to know advanced Python concepts?
-
#132 Miguel Grinberg said
@Tania: Glad it worked. You do not need to be an expert Python coder, but like with this tutorials, if you come across something you didn't know before, it would be a good idea to research that new concept. The most important thing to know is how modules and packages work in Python, because that is the key to the application structure, both here in these tutorials and in the book.
-
#133 Olivia said
Hi Miguel,
Thanks for your post, but when I run ./run.py, it is showing me these 2 lines:
* Running on http://127.0.0.1:5000/
* Restarting with reloader
And the process goes on forever and my http://localhost:5000 has no connections.. Do you have any ideas? Thanks! -
#134 Miguel Grinberg said
@Olivia: I'm not sure, that should have worked. I assume you are running the browser on the same computer as the Flask server, correct?
-
#135 Ata said
<h1>!flask/bin/python</h1>it's wrong, because /python in bin is not a folder, is it?
-
#136 Miguel Grinberg said
@Ata: No, that's correct. The shebang line needs to point directly to the executable not to a folder.
-
#137 scott said
sorry, for the delay. I figured out the virtualenv and got the progrm to run on the beagleboard. I ended up reinstalling virtualenv, think it was a missing lib. All is good, very cool. Thanks again for this exceptional tutorial.
-
#138 Eko Wibowo said
My first encounter with a Flask application is using this tutorial. Inspired by this tutorial and the one authored by Shekhar Gulati in Openshift, https://www.openshift.com/blogs/build-your-app-on-openshift-using-flask-sqlalchemy-and-postgresql-92, I start my own Flask Tutorial using Openshift as the PaaS environment. I hope I can contribute something to the amazing world of Python!
-
#139 Siyuan said
Hi Miguel,
I am confused with the "from app import app"statement in app/init.py and app/views.py. After I created init.py and views.py, I cd to the app directory and run the python interpreter in ../flask/bin, then type in "from app import views" or "import app". The console shows "ImportError: No module named app". But I run the run.py in microblog, it is ok.
init.py and views.py are in the app directory, why they can still import the app package? Please clarify my mind.
Thanks. -
#140 Miguel Grinberg said
@Siyuan: you do not need to "cd" into "app", run the Python console from one directory above app and the package will import just fine.
-
#141 Sajeev Zacharias said
I found this tutorial so comfortable and I wish the next chapters also will be in this way. I was following a flask video tutorial from tutsplus.com and I found it so terrible. That is why, I switched to this one. This is nice.
-
#142 david said
very good
-
#143 Luke said
-
#144 Damien said
A handy oneliner for easy installation of flask virtualenv:
curl https://raw.github.com/pypa/virtualenv/1.9.X/virtualenv.py | python - flask
-
#145 shrikant said
It is really nice article, very helpful
-
#146 Miguel Grinberg said
@Luke: Flask does not come as a single file, you have to install it. Flask has more features than Bottle and has more extensions, but for small apps they are pretty much equivalent, so if bottle does what you want I think it is a very good option.
-
#147 liblib said
Miguel thank you for this step by step tutorial
as I'm running this on compute engine instance when opening the browser on my local machine and entering the url i get "Oops! Google Chrome could not connect to localhost:5000" this happens although I open the run command to host 0.0.0.0 like so app.run(host = '0.0.0.0' , debug = True) what else should i do to see the hello world? -
#148 Miguel Grinberg said
@liblib: you need to use the IP address of your server instead of localhost. The "localhost" name is an alias for your own machine.
-
#149 Bill said
Hello Miguel. Looks like I'm late to the party but still I thank you for posting this tutorial. I have been a programmer for a long time also. A friend of mine has talked me into giving Python a try. I plan on working though this tutorial, so again, thanks in advance.
-
#150 PeterD said
It is probably too late to hit the source code and the book, but if you really want the better shebang to use on Linux systems to get to the system Python interpreter,
replace this line:
<h1>!/usr/bin/python</h1>with this line:
<h1>!/usr/bin/env python</h1>Why is this so important you ask?
Because /usr/bin/env can interpret your $PATH, which makes scripts more portable.
<h1>!/usr/bin/python</h1>Will only run your script if python is installed in your system's /usr/bin directory.
<h1>!/usr/local/bin/python</h1>Will only run your script if python is installed in your /usr/local/bin directory.
<h1>!/usr/bin/env python</h1>Will interpret your system's $PATH environment variable, and find python in any directory your system designers decided to install Python to and marked in your system's $PATH environment variable.
So your script is more portable, and will work without modification on systems where python is installed as /usr/bin/python, or /usr/local/bin/python, or even custom directories (that have been added to $PATH), like /opt/local/bin/python.
Portability is the only reason using env is preferred to hard coded paths.
This should cut down on some technical support calls and emails from readers of the book, the web site and if readers use this in their own code cut down on some technical support calls and emails from their end users.