Getting Started with Flask, a Python Microframework

Kabaki Antony

In this article, we’ll introduce Flask, a popular microframework for Python that offers an alternative to the giant that is Django.

Flask is designed to be lightweight and flexible, allowing developers to create web apps quickly and easily. In this article, we’ll cover what Flask is, its key features, the benefits of its simple API, its flexibility in supporting third-party extensions, the most common Flask extensions, and when is and isn’t a good time to use Flask.

What Is Flask?

Flask is a micro web framework written in Python that’s used for developing web applications. It’s built on a simple philosophy of keeping things simple and lightweight, giving developers only the most important tools needed to build web apps without unnecessary complexity.

It’s built on top of the Werkzeug WSGI toolkit, which provides web server functionality needed for handling requests and responses, and the Jinja2 templating engine, which gives Flask the ability to handle HTML templates, allowing developers to create dynamic web applications.

Here are some of the key features of Flask that make it such a great framework to work with:

  • It has a simple API for creating web routes and handling requests.
  • The Jinja templating engine offers support for HTML templates, allowing developers to create web pages easily.
  • It’s highly extendable, due to its support for third-party extensions, so a developer can install extensions depending on their project needs.
  • It comes bundled with a development server that makes it easy to test and debug apps.

Overall, Flask provides a powerful, flexible, yet simple framework for building web applications. It’s a good choice for both new and experienced web developers, and is one of the most popular web frameworks in the Python web development ecosystem.

Advantages of Flask

Let’s now take a more detailed look at some of the advantages of using Flask in development.

Simplicity. Flask’s design philosophy emphasizes simplicity, which makes it easy for developers at any level to understand and use. This also means that developers have a very minimal learning curve, since they only need to learn a few concepts and APIs to get started building web applications.

Flexibility. The micro nature of Flask — providing only the core features of a web framework — gives developers the power to customize and extend it to suit their requirements using Flask extensions or third-party libraries.

Documentation. The Flask documentation is very comprehensive, with good coverage of basic to advanced topics, making it very easy for developers to learn how to use the framework.

Compatibility. Flask is compatible with a wide range of Python versions, which makes it easy to use with existing Python codebases. It also has support for multiple web servers, which makes it easy to deploy it on a variety of hosting platforms.

Quick development. Flask’s simplicity and flexibility reduce the boilerplate needed to set up an application, allowing developers to get started quickly.

Around the Web, Flask is used in a lot of interesting ways. A few notable examples are:

  • PgAdmin. The Postgres admin interface runs on a Flask instance, giving developers an interface where they can manage their Postgres databases.
  • Twilio. This is a communication platform that uses Flask in several of its APIs.
  • Pinterest. This photo-sharing app uses Flask in the web development stack, allowing its team to create some custom features and integrations easily.

When to Use Flask

Flask’s simplicity and ease of use make it an excellent choice for a wide range of web projects:

  • Prototyping. Its ease of use and flexibility make it an excellent choice for quickly creating prototypes allowing developers to build and test new features fast.
  • Creating RESTful APIs. Its own simple API makes it easy to create and handle HTTP requests.
  • Ecommerce apps. It works well for building online marketplaces and ecommerce platforms.
  • Finance. It’s useful for building financial applications, with account management, transaction processing, and investment tracking.
  • AI. It offers a useful and straightforward way to build and deploy AI training models.

When Not To Use Flask

While Flask is a great framework and has a number of advantages and great features, there are situations these features work against it. Let’s explore some of the projects that suit other types of frameworks better.

Projects that require built-in functionality. Being a microframework, Flask only provides the core bits needed to create a web application. If a project requires, say, an admin interface, authentication, or an ORM, then Django is a better option.

Projects with strict security requirements. As Flask is a flexible framework, we have to rely on third-party extensions to implement some level of security in our apps. While this certainly works, it’s better to rely on a more battle-tested framework that takes a more secure approach, such as Tornado or Twisted.

Projects that enforce some coding standard. Due to Flask’s flexibility, developing applications on it leaves developers to make apps in any way they see fit. However, frameworks like Django ensure that developers follow a particular convention, meaning that developers can move from one project to other easily.

Setting Up a Flask Development Environment

Let’s now look at how to get started with Flask, from setting up the development environment, to installation, and finally spinning up a minimal application.


Python has to be installed on the development machine. Here are instructions for that (although we may already have it installed).

Create a Virtual Environment

A virtual environment is an isolated Python environment where we can install packages for a given project without affecting the global Python installation. (Here’s further discussion about why virtual environments are useful.) There are different packages for creating virtual environments in Python, such as virtualenv, venv, or Conda.

In this article, we’ll use virtualenv. We can install it with the following command:

pip install virtualenv

Once virtualenv has been installed, we can create a directory where our Flask application will reside. We can call the directory whatever we want — other than Flask, as that will cause conflicts. We’ll call ours flask_intro:

mkdir flask_intro

Next, change into that directory so that we can start using it:

cd flask_intro

In that directory, let’s now create our virtual environment, using the following command:

virtualenv myenv

The command above creates a virtual environment and calls it myenv. Let’s activate it so that we can install Flask in it. To activate the virtual environment on Linux or macOS, use the following command:

. myenv/bin/activate

On Windows, use this command:

. myenv\Scripts\activate

Once our virtual environment has been activated, it will show the name of the virtual environment on the shell prompt, similar to the output below:

(myenv)/~(path to your project directory)$

Within our activated virtual environment, we can go ahead and install Flask, using the following command:

pip install Flask

Once Flask finishes installing, let’s go ahead and create a minimal application. We’ll create a module that will hold our Flask application. For simplicity’s sake, let’s call it On Linux or macOS we can use the following command to create the file in our flask_intro directory:


The command above creates a file named We could also use a development environment to create the file. Once the file has been created, put the below code in it and save it:

from flask import Flask
app = Flask(__name__)
def hello_world():
    return 'Hello, World!'

In the code above, we import the Flask class from the flask module, then create an instance of Flask that we call app and pass the __name__ variable.

Then we have the route decorator @app.route(“\”), which means that the hello_world() function will be triggered when someone visits the root route of our application once it’s run.

There are various ways that we could run the application, so let’s look at some of them. The first way is to supply the flask command with a number of arguments: --app, then the name of the module that holds, our Flask application, and then run. See below:

flask –app <the name of your module> run

Using the example above to run our sample application:

flask –app hello run

That will run our application on the default port 5000 so the application will be available on http://localhost:5000/ or at If we want the application to be available on a different port, we can specify the port using -p or --port option. For example:

flask --app hello run --port=8080

That will run the server on port 8080. The other way we can run the application is by just using the flask run commands. However, for us to be able to do that, we need to tell Flask the name of the module that will hold the Flask instance, and we do that by setting the FLASK_APP environment variable. So in our case, the Flask application is contained in a file named So we can set it this way:

export FLASK_APP=hello

Now that we’ve set the FLASK_APP environment variable, we can run the development server like so:

flask run

With that code, we now have a web application running. This demonstrates the core philosophy of Flask: we don’t need a lot of boilerplate code to get things going. However, the application we’ve set up above isn’t very functional or useful, since it only renders the string “Hello World!” on our web page. To do anything more useful, we can turn to templates. We’ll look at how to handle them next.

Flask Templates

Flask templates are a way to create dynamic web pages that can display different content based on various factors, such as data from a database, or user input. Templates in Flask are a combination of HTML and special placeholders called template variables that are replaced with actual values at runtime.

Templates are stored in the templates directory. So to use templates, we need to import the render_template() method from flask. The render_template() method takes a template name and any optional data that needs to be passed to the template.

Let’s see an example of a function that uses a template to render a web page:

from flask import Flask, render_template
app = Flask(__name__)
def index():
    title = 'Welcome to my website!'
    message = 'This is an example of using Flask templates.'
    return render_template('index.html', title=title, message=message)

In the example above, we have a view function — index() — that’s bound to the root URL (“/”) by the @app.route() decorator. The function has two variables, title and message. Finally, we pass the template index.html to the render_template(), together with the title and message variables.

For the code above to work, we need to have an index.html template residing in a templates directory. So the template will look something like this:

# index.html
<!doctype html>
    <title>{{ title }}</title>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>

In the index.html file, the placeholders {{title}} and {{ message }} are replaced with the values passed to the template in the render_template() method.

Templates can also include more complex logic such as if statements and for loops, which allow for more dynamic pages to be generated.

So templates in Flask provide developers with a very powerful option for creating dynamic web pages rich with user-generate information.

Flask Routing

Most web applications will have more than one URL, so we need to have a way of knowing which function handles which URL. In Flask, this mapping is known as routing — the process of binding or mapping URLs to view functions. Binding URLs to view functions allows the application to handle different types of requests, such as GET, POST, PUT, DELETE, and more. It also enables the application to handle multiple requests from different clients.

To set up routes in Flask, we use the route() decorator. The decorator binds a URL to a view function — so when a user visits a URL that exists on our application, Flask triggers the associated view function to handle the request.

Let’s see an example:

from flask import Flask, render_template

app = Flask(__name__)

def about():
    return "This is the about page"

In the example above, we define an about URL (/about). When the application receives a request for the about URL, Flask calls the about() function, which returns the string “This is the about page”.

So far, even though these examples return different pages, they all just use the GET HTTP request. In order to be able to handle any specific request, we can specify the HTTP method as an optional argument to the route() decorator.

Let’s see an example of a PUT request:

from flask import Flask, request

app = Flask(__name__)

@app.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    # get the user data from the request body
    data = request.get_json()
    # do something with the user data, such as update the user in the database
    # ...
    # return a response indicating success or failure
    return {'message': f'User {user_id} updated successfully'}, 200

In this example, we define a route that handles a PUT request to update user details given their user_id. We use <int:user_id> in the route to indicate that the user ID should be an integer.

In the update_user() function, we get the user data from the request body using the request.get_json() method. We do something with the user data, such as updating the user in the database, and then return a response indicating success or failure along with an HTTP status code (a 200 in this case to show success).

Overall, routing allows Flask to be able to handle different types of requests and allows our application to handle and act on data differently, depending on the URL that a user visits.

Flask Forms and Validation

Apart from displaying data for users, Flask templates can also take input from users for further processing or storage. For that, Flask provides built-in support for processing HTML forms and handling user input. Flask forms are based on the WTForms library, which provides a flexible and powerful way to handle form data and perform validations. However, the library isn’t a part of the standard Flask installation, so we need to install it using the following command:

pip install WTForms

Once we’ve installed WTForms, to use forms in Flask we need to define a form class that will inherit from flask_wtf.FlaskForm. The class will contain the fields that are going to be on the form and any validation rules that should be applied to them.

Let’s see an example of a login form:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length

class LoginForm(FlaskForm):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired(), Length(min=6)])
    submit = SubmitField('Log In')

In the example above, we define a login form with two fields — email and password — and a submit button. We also have a validators argument that’s used to specify validation rules for each field. For example, in this case we require the email field to contain a valid email address and the password field to contain a password of no fewer than six characters.

Once we’ve defined the form class, we can use it in the login view function to render the form and process the form data submitted by the user. Let’s see an example of the view function:

from flask import render_template, request
from .forms import LoginForm

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        email =
        password =
        # do something with the form data
    return render_template('login.html', form=form)

In the example above, we have a login view that accepts two HTTP methods (GET and POST), so when users access the URL from a browser the LoginForm is rendered as an HTML form using the render_template method, and when a user submits the form we check if the form is valid using the validate_on_submit method. If the form is valid, we access the email and password.

The login.html form could look something like this:

# login.html
<form method="POST">
  {{ form.csrf_token }}
    {{ }} {{ }}
    {% for error in %}
    <span style="color: red;">[{{ error }}]</span>
    {% endfor %}
    {{ form.password.label }} {{ form.password() }}
    {% for error in form.password.errors %}
      <span style="color: red;">[{{ error }}]</span>
    {% endfor %}
  {{ form.submit() }}

The above template will render the email and password fields, along with their labels, and a submit button with the text “Login”. The form.csrf_token field is included to prevent cross-site request forgery (CSRF) attacks. The {% for %} loops are used to display any validation errors that may occur.

By using Flask forms, we have a powerful way of handling user input, and we’ll be able to validate the data they input.

Flask Extensions

As we’ve seen, Flask is a microframework that only includes the most important parts needed to create a web application. However, if we need to add functionality that isn’t offered out of the box by Flask, we need to add packages to the installation. Flask extensions are the way we provide this additional functionality. We can simply install the package we need. There are many extensions made by the Flask community.

Here are some of the most popular ones:

  • Flask-SQLAlchemy: provides integration with the SQLAlchemy toolkit that makes it easy to interact with databases.
  • Flask-Login: provides user authentication and session management to Flask.
  • Flask-Mail: provides a simple interface to send emails from Flask.

There are hundreds of extensions made by the Flask community to handle different functionality. Using the extensions is generally straightforward. First, we need to install the extension we want using pip.

Let’s see an example of using Flask-SQLAlchemy. First, we need to install it:

pip install flask-sqlalchemy

Next, we need to configure it. For example:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

In the example above, we have a User model with a username and email field. We also configure SQLALCHEMY_DATABASE_URI, indicating that we’re using an SQLite database located at example.db. With that set, we now have access to the db object that allows us to interact with the database. For example, we could create a new user and add it to the database, like so: 
from app import db, User

user = User(username='john', email='')

With Flask extensions, our application is able to have more functionality than it would normally have with the core Flask implementation.


In this article, we introduced Flask, a lightweight and flexible web framework for Python. We discussed the advantages of using Flask for web development, including its simplicity, flexibility, and ease of use. We also covered how to set up a development environment, create routes, use templates, handle forms, and use extensions like Flask-SQLAlchemy.

To summarize, Flask is a great choice for building web applications of any size, from small personal projects to large-scale commercial applications. It’s easy to learn and use, but also offers advanced features through its many extensions.

If you’re interested in learning more about Flask, here are some additional resources:

If you’d like to learn more about Django and Flask and their best use cases, check out Python Web Development with Django and Flask.