Patrick's Software Blog

My Favorite Python Packages for Building Flask Applications

Rocks stacked on top of each other with the Flask logo in the top left corner and the Python logo in the bottom right corner.

Introduction

With over 450,000 Python packages available for download from PyPI, it can be overwhelming to figure out which Python packages to use when building a Flask application. This blog post lists (in no particular order) the Python packages that I prefer to use when building Flask applications.

Why use a Python package?

Building a web application is challenging. Trying to build a web application completely from scratch (i.e. only using the Python language) would be incredibly time-consuming and full of security problems.

The idea of building a custom hashing algorithm for storing user passwords could turn into months of work; that's only a small piece of a web application!

By using Python packages for your Flask application, you're leveraging the expertise of other software developers, as well as the bug fixes and lessons learned that have been incorporated into these packages.

1. APIFairy

If you want to build an API with Flask, I think APIFairy is the best solution.

APIFairy is an API framework that allows for easily creating an API with Flask. It provides the key functionality needed for an API backend:

Functionality Description Supporting Python Package(s)
Request Parsing Parse query string of the URL -OR- input data (JSON) flask-marshmallow, marshmallow
Response Generation Generate output (JSON) flask-marshmallow, marshmallow
Documentation Automatically generate API documentation (OpenAPI 3.x standard) apispec
Authentication/Authorization Guard API endpoints based on specific authentication/authorization requirements Flask-HTTPAuth

Here's an example of an API endpoint for adding an entry:

API Endpoint for adding a new journal entry with Flask and APIFairy

Based on my experience in developing APIs using APIFairy, it is the perfect combination of providing control of the API endpoints and authentication, while still "feeling" like a traditional Flask application.

For a tutorial on how to build a RESTful API using Flask and APIFairy, check out my tutorial on TestDriven.io: Building a Flask API with APIFairy

2. Frozen-Flask

An overlooked use of Flask is for developing static websites. Frozen-Flask is an excellent Python package for generating a static website, as it will automatically generate static files for all URLs.

If you're already comfortable with developing apps using Python and Flask, then you can continue to use the same tools and workflow for developing a static website:

  • Jinja templates (including template inheritance) for generating HTML code
  • Blueprints for organizing the project
  • Development server with hot reloading when changes are made (no need for any complicated compilation step)
  • Testing using pytest

After developing a Flask project, you can use Frozen-Flask to generate the static files:

from flask_frozen import Freezer
from project import create_app

# Call the application factory function to construct a Flask application
# instance using the development configuration
app = create_app()

# Create an instance of Freezer for generating the static files from
# the Flask application routes ('/', '/breakfast', etc.)
freezer = Freezer(app)


if __name__ == '__main__':
    # Generate the static files using Frozen-Flask
    freezer.freeze()

At this point, the static files (in the /build directory) can be served using any static site hosting solution (Netlify, Render, etc.).

For a tutorial on how to build a static website using Frozen-Flask and then deploy it to Netlify, check out my tutorial on TestDriven.io: Generating a Static Site with Flask and Deploying it to Netlify

3. Flask-SQLAlchemy

Flask-SQLAlchemy has become the standard for interacting with a relational database when building a Flask application.

Flask-SQLAlchemy makes it easier to use SQLAlchemy with a Flask application. SQLAlchemy is an Object Relational Mapper (ORM) that allows you to use Python to interact with a relational database.

With Flask-SQLAlchemy, you define a relational database table using Python:

class Book(database.Model):
    __tablename__ = 'books'

    id = mapped_column(Integer(), primary_key=True, autoincrement=True)
    title = mapped_column(String())
    author = mapped_column(String())
    rating = mapped_column(Integer())

You can easily create the database using:

(venv)$ flask shell
>>> from project import database
>>> database.create_all()
>>> quit()

Writing SQL statements to query, create, and delete can be very difficult; SQLAlchemy makes this more straight-forward:

# Query an individual book
query = database.select(Book).where(Book.id == id)
book = database.session.execute(query).scalar_one_or_none()

# Add a new book
new_book = Book(book_data.title, book_data.author, book_data.rating)
database.session.add(new_book)
database.session.commit()

# Delete a book
database.session.delete(book)
database.session.commit()

Additionally, Flask-Migrate can be used to ease the pain of performing database migrations (especially when in production!).

4. Gunicorn

The Flask development server is great for serving up a Flask application locally. As the name suggests, the "development" server is not meant for production, though. Instead, you should use Gunicorn, a production-grade WSGI web app server.

WSGI, which stands for Web Server Gateway Interface, is an interface between a web server and a web app since a web server cannot talk directly to a Python app.

Gunicorn should be used for running a Flask application in production. For example, a Flask application can be run using 2 workers:

$ gunicorn --workers=2 app:app

As the description (a Python WSGI HTTP Server) of Gunicorn states, it handles web requests (HTTP calls) to the server and executes the Flask application to process the request.

To see how Gunicorn can be used in production, check out my tutorial on TestDriven.io: Deploying a Flask App to Render

5. pytest

pytest is a test framework for Python used to write, organize, and run test cases. After setting up your basic test structure, pytest makes it easy to write tests and provides a lot of flexibility for running the tests.

pytest satisfies the key aspects of a good test environment:

  • tests are fun to write
  • tests can be written quickly by using helper functions (fixtures)
  • tests can be executed with a single command
  • tests run quickly

If you're interested in really learning all the different aspects of pytest, I highly recommend the Python Testing with pytest book by Brian Okken.

Also, if you want to check the code coverage of your tests, pytest-cov is a great package that integrates seamlessly with pytest.

For a tutorial on how to test a Flask application with pytest, check out my tutorial on TestDriven.io: Testing Flask Applications with Pytest

6. Flask-Login

Flask-Login is the perfect example of functionality that you could write yourself, but it is so much better to use a well-tested package for some key user management features.

The Flask-Login documentation is excellent, as it clearly outlines what this package does vs. what it does and does not do:

Features:

  • Store the active user's ID in the session, and let you log them in and out easily.
  • Let you restrict views to logged-in (or logged-out) users.
  • Handle the normally-tricky "remember me" functionality.
  • Help protect your users' sessions from being stolen by cookie thieves.

However, it does not:

  • Impose a particular database or other storage method on you.
  • Handle permissions beyond "logged in or not."
  • Handle user registration or account recovery.

In summary, I use Flask-Login to help with:

  • Logging a user in and out (login_user and logout_user, respectively)
  • Restricting the view functions that non-logged-in users can access (@login_required decorator)
  • Handling the 'Remember Me' functionality (remember argument for login_user)
  • Loading the current user from the session object (current_user)

7. Flask-Sessions

There are two types of sessions commonly used in web development:

  1. Client-side - sessions are stored client-side in browser cookies
  2. Server-side - sessions are stored server-side (typically a session identifier is then created and stored client-side in browser cookies)

Flask uses the client-side approach as the built-in solution to sessions.

Flask-Session is an extension for Flask that enables server-side sessions. It supports a variety of solutions for storing the session data on the server-side:

  1. Redis
  2. Memcached
  3. SQLAlchemy
  4. MongoDB

For a tutorial on how to use Flask-Session with Redis, an in-memory data structure store, check out my tutorial on TestDriven.io: Server-side Sessions in Flask with Redis

8. pydantic

pydantic is a Python package for data validation and settings management using Python type annotations.

While pydantic is often associated with FastAPI, it can help out with Flask applications for data validation.

I use pydantic for server-side form validation:

from pydantic import BaseModel, ValidationError, validator


class BookModel(BaseModel):
    """Class for parsing new book data from a form."""
    title: str
    author: str
    rating: int

    @validator('rating')
    def book_rating_check(cls, value):
        if value not in range(1, 6):
            raise ValueError('Book rating must be a whole number between 1 and 5')
        return value


@app.post('/books/add')
def add_book():
    book_data = BookModel(
        title=request.form['book_title'],
        author=request.form['book_author'],
        rating=request.form['book_rating']
    )

    # Save the new book to the database

pydantic is an example of a great Python package that applies to all Python projects, including Flask projects.

9. Flask-WTF

If you work with forms in a Flask application, then Flask-WTF can make the process easier.

Flask-WTF is a Flask-specific wrapper around WTForms, a powerful form validation and rendering library.

The process that I use for creating forms with Flask-WTF is to create a new:

  1. Class in forms.py defining the elements of the form
  2. Route in routes.py for generating the form page and for processing the data submitted via the form
  3. Template file for defining the layout of the page displaying the form

Flask-WTF protects against Cross-Site Request Forgery (CSRF), which is one of the more common types of attacks on websites. It's reason enough to use it.

10. Flask-Mail

Flask-Mail is a Flask extension to send emails from a Flask view function.

Important: Flask-Mail is not actively maintained; nevertheless, it's a stable, widely-used Python package so it's fine to use.

Flask-Mail makes sending emails from a Flask application much easier than working directly with the built-in smtplib module in Python.

Also, Flask-Mail provides a convenient testing environment for checking that emails are queued up to be sent during testing (without actually being sent to an SMTP server).

If you're concerned about using a non-maintained Python package, Flask-Mailman is an alternative solution.

Conclusion

The Flask and Python ecosystems should be leveraged to help develop a Flask application. If you pick reputable Python packages, you're going to save yourself an incredible amount of time that you can use to build a web application in Flask.