Flask, from zero to hero: the complete tutorial (work in progress).

mattia toselli
7 min readMar 28, 2022

Flask is a web framework, written in Python that lets you develop web applications easily and faster. Actually, more in depth, it’s a microframework that is extensible and ready to use. It grows with your needs and application.

Why should I use Flask?

It’s easy to get started with Flask, it doesn’t have a huge learning curve, actually it’s very explicit, which increases readability, readability means less bugs, and faster development.

Simpler Development if you love Python. If you understand Python well, then you’ll be able to move around and contribute to a Flask application pretty easily. It’s less opinionated so fewer standards to learn (actually, this means that you have to be a good developer in order to contribute to a Flask project).

Flask is a micro framework, that means it’s a “low-level” tool. There are fewer levels of abstraction between you and the below functionalities, like database, cache, etc.

The project

In this tutorial we are going to build a litttle CRM (customer relationship manager), this is actually a side project I am working on, so you’ll work on an actual project that is going to go online, in my company I need a CRM for my commercial agents to keep track of contacts, collaborators, tickets and deals, so instead of buying an expensive Salesforce or HubSpot license, I am going to develop it by myself and give it to a developer to maintain.

I am a Symfony developer, so usually I work in PHP, but i decided to use Flask since these days younger developers prefer Javascript or Python and I prefer to be able to find developers quicly if I need to.

The project will make use of some pages, templates, and ajax calls, written in Vue.js.

Installing Python and creating a virtual environment

If you don’t have Python installed on your computer (useually Linux and Mac do), go ahead and install it now. If your operating system does not provide you with a Python package, you can download an installer from the Python official website. In order to check if you have Python 3 installed, try the command below.

$ python3Python 3.9.5 (default, Nov 18 2021, 16:00:48) 
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

In Python, packages such as Flask are available in a public repository, to install a package on your machine use pip as follows:

$ pip install <package-name>

BUT… I want you to think about installing packages globally on your machine, if you are a good developer, you should ALWAYS prefer another way, like for example containerization (like Docker) or at least, different environments, in order to be able to use different packages versions if you are going to develop multiple apps in Flask on your computer.

Let’s start by creating the project directory.

$ mkdir CRM
$ cd CRM

Support for virtual environments is included in all recent versions of Python, so all you need to do to create one is this, )you’ll probably need to install the python-venv package):

$ python3 -m venv venv

With this command, I’ll create a virtual environment named venv. The first venv in the command is the name of the Python virtual environment package, and the second is the virtual environment name.

Now you have to tell the system that you want to use this virtual environment, and you do that by activating it.

$ source venv/bin/activate
(venv) $ _

The changes made to your terminal session are all temporary and private to that session, so they will not persist when you close the terminal window.

Now that you have a virtual environment created and activated, you can finally install Flask in it:

pip install flask

Hello World and packages

Let’s start with a simple application, and as always, we’ll start by prompting on the console the famous “Hello World!” message.

In Python, a sub-directory that includes a __init__.py file is considered a package, and can be imported. When you import a package, the __init__.py executes and defines what symbols the package exposes to the outside world. Let’s create a package called app, that will host the application.

$ mkdir app
$ cd app
$ touch __init__.py

app/__init__.py:

from flask import Flask
app = Flask(__name__)
from app import routes

The __name__ variable passed to the Flask class is a Python predefined variable, which is set to the name of the module in which it is used. The application then imports the routes module, which doesn’t exist yet.

Theroutes module is imported at the bottom and not at the top of the script as it is always done. The bottom import is a workaround to circular imports, a common problem with Flask applications. You are going to see that the routes module needs to import the app variable defined in this script, so putting one of the reciprocal imports at the bottom avoids the error that results from the mutual references between these two files.

The routes are the different URLs that the application implements.

app/routes.py:

from app import app@app.route('/')
@app.route('/index')
def index():
return "Hello, World!"

To complete the application, you need to have a Python script at the top-level that defines the Flask application instance. Let’s call it server.py, we’re ready to spin up the server:

(venv) ~/CRM$ flask run
* Serving Flask app 'server.py' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

if you head to http://127.0.0.1:5000, or http://127.0.0.1:5000/index you’ll see your development server responding.

If you enter any other URL you will get an error, since only these two URLs are recognized by the application.

Using Flask environment variables

Flask allows you to register environment variables, they are usefull if you need to work in a team and you use different environments. Those variables are automatically imported when you run the flask command. To use this option you have to install the python-dotenv package:

(venv) $ pip install python-dotenv

Then you can just write the environment variable name and value in a file named .flaskenv located in the top-level directory of the project:

.flaskenv:

FLASK_APP=server.py

Templates

If you followed the first part of this tutorial, you may have noticed that we are able to return a string in our Flask functions and link those functions to URLs. It should be obvious that if we wanted we could return an entire HTML page, but of course it would be a mess, and tht’s why we prefer to use templates. Templates help achieve separation between presentation and business logic. In Flask, templates are written as separate files, stored in a templates folder that is inside the application package.

Let us create the folder and let’s begin by creating a simple page.

mkdir templates
cd templates
touch index.html

app/templates/index.html:

<!DOCTYPE html>
<html lang="it" dir="ltr">
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>
<body>
<h1>Good Morning, {{ user.username }}!</h1>
</body>
</html>

We are using the template engine functions here, a template engine called Jinja, that comes with Flask, template engines allow developers to use certain syntax to manipulate data from the backend. Names beetween the moustache must come from the backend as named variables and as dictionaries.

edit app/routes.py by importing the Flask function render_template(), and let us pass the variables:

from app import app
from flask import render_template
@app.route('/')
@app.route('/index')
def index():
user = {'username': 'Mattia'}
return render_template('index.html', title='Home', user=user)

we will use Jinja syntax very much in this tutorial, so keep reading if you are interested.

Introduciotn to the concept of extending templates

Most web applications these days have many parts of the page in common, like for example a navbar, with a few frequently used links. Of course, we can easily add a navigation bar to every template we use in our app, but let’s stop for a minute, and think about it. What are we going to do when we will need to edit that navbar in hundreds of templates? As a developer, you should always be aware that it is a good practice to not repeat yourself if that is possible.

Jinja2 has a template inheritance feature that solves this problem. In essence, you can define page layouts that are common to other templates, from which other templates are derived. Changing the father template, will reflect the changes in all templates extending the base one.

A common use of this feature for example is to import static assets like css framworks or javascript libraries.

In this example, we are going to use this feature to import Bootstrap CSS framework and VueJS, we will also use a free template from Bootstrap, I chose this one: https://themewagon.com/themes/free-responsive-bootstrap-5-html5-admin-template-sneat/.

Introduction to static files

Usually i prefer to save the templates i use in a public access folder, so that me or other developers are always able to reach it.

Let us just extract the zip file in a new folder in app/static.
The graphical mock of the application will be now availble at http://127.0.0.1:5000/static/graphic/sneat-1.0.0/html/index.html.

All of the javascript, css and other static files will be available in this folder, we will see how to import static files in the next section, where we are going to merge these two introductions paragraphs together.

--

--

mattia toselli

Software developer at Fluentify LTD. AWS, Docker and programming enthusiast.