Let’s Know How To Structure Large Flask Applications Step by Step

Creating and managing Large Flask Applications involves various methods and conventions. Many frameworks provide tools for automating and simplifying this task, but they all emphasize structuring the code base by logically distributing it across files and folders.

Flask, a minimalistic web application development framework, offers a solution through its ‘blueprints.’

In this article, we’ll explore how to establish an application directory and organize it to accommodate reusable components using Flask’s blueprints. This approach streamlines the maintenance and development of application components significantly.

Transitioning from conventional methods to Flask’s blueprints can make the process more efficient and manageable. Let’s delve into this approach for building robust Flask applications.

Glossary

1. Flask: The Minimalist Application Development Framework

2. Our Choices In This Article

3. Preparing The System For Flask

  • Prepare The Operating System
  • Setting up Python, pip and virtualenv

4. Structuring The Application Director

  • Creating Application Folder
  • Creating A Virtual Environment
  • Creating Application Files
  • Installing Flask

5. Working With Modules And Blueprints (Components)

  • Module Basics
  • Module Templates

6. Creating The Application (run.py, init.py, etc.)

  • Edit run.py using nano
  • Edit config.py using nano

7. Creating A Module / Component

  • Step 1: Structuring The Module
  • Step 2: Define The Module Data Model(s)
  • Step 3: Define Module Forms
  • Step 4: Define Application Controllers (Views)
  • Step 5: Set Up The Application in “app/init.py”
  • Step 6: Create The Templates
  • Step 7: See Your Module In Action

Flask: The Minimalist Application Development Framework

Flask is a minimalist (or micro) framework which refrains from imposing the way critical things are handled. Instead, Flask allows the developers to use the tools they desire and are familiar with. For this purpose, it comes with its own extensions index and a good amount of tools already exist to handle pretty much everything from log-ins to logging.

It is not a strictly “conventional” framework and relies partially on configuration files, which frankly make many things easier when it comes to getting started and keeping things in check.

Our Choices In This Article

As we have just been over in the previous section, Flask-way of doing things involves using the tools you are most comfortable with. In our article, we will be using – perhaps – the most common (and sensible) of choices in terms of extensions and libraries (i.e. database extraction layer). These choices will involve:

  • SQLAlchemy (via Flask-SQLAlchemy)
  • WTForms (via Flask-WTF)

Flask-SQLAlchemy

Adds SQLAlchemy support to Flask. Quick and easy.

This is an approved extension.

Flask-WTF

Flask-WTF offers simple integration with WTForms. This integration includes optional CSRF handling for greater security.

This is an approved extension.

Preparing The System For Flask

Before we begin structuring a large Flask application, let’s prepare our system and download (and install) Flask distribution.

Note: We will be working on a freshly instantiated droplet running the latest version of available operating systems (i.e. Ubuntu 13). You are highly advised to test everything on a new system as well – especially if you are actively serving clients.

Prepare The Operating System

In order to have a stable server, we must have all relevant tools and libraries up-to-date and well maintained.

To ensure that we have the latest available versions of default applications, let’s begin with updates.

Run the following for Debian Based Systems (i.e. Ubuntu, Debian):

To get the necessary development tools, install “build-essential” using the following command:

Setting up Python, pip and virtualenv

On Ubuntu and Debian, a recent version of Python interpreter – which you can use – comes by default. It leaves us with only a limited number of additional packages to install:

  • python-dev (development tools)
  • pip (to manage packages)
  • virtualenv (to create isolated, virtual

Note: Instructions given here are kept brief. To learn more, check out our how-to article on pip and virtualenv: Common Python Tools: Using virtualenv, Installing with Pip, and Managing Packages.

pip

pip is a package manager which will help us to install the application packages that we need.

Run the following commands to install pip:

virtualenv

It is best to contain a Python application within its own environment together with all of its dependencies. An environment can be best described (in simple terms) as an isolated location (a directory) where everything resides. For this purpose, a tool called virtualenv is used.

Run the following to install virtualenv using pip:

Structuring The Application Directory

We will use the exemplary name of LargeApp as our application folder. Inside, we are going to have a virtual environment (i.e. env) alongside the application package (i.e. app) and some other files such as “run.py” for running a test (development) server and “config.py” for keeping the Flask configurations.

The structure – which is given as an example below – is highly extensible and it is built to make use of all helpful tools Flask and other libraries offer. Do not be afraid when you see it, as we explain everything step by step by constructing it all.

Target example structure:

Creating Application Folders

Let’s start with creating the main folders we need.

Run the following commands successively to perform the task:

Our current structure:

Creating A Virtual Environment

Using a virtual environment brings with it a ton of benefits. You are highly suggested to use a new virtual environment for each one of of your applications. Keeping the virtualenv folder inside your application’s is a good way of keeping things in order and tidy.

Run the following to create a new virtual environment with pip installed.

Creating Application Files

In this step, we will form the basic application files before moving on to working with modules and blueprints.

Run the following to create basic application files:

Our current structure:

simple code

Installing Flask And Application Dependencies

Once we have everything in place, to begin our development with Flask, let’s download and install it using pip.

Run the following to install Flask inside the virtual environment env.

Note: Here we are downloading and installing Flask without activating the virtual environment. However, given that we are using the pip from the environment itself, it achieves the same task. If you are working with an activated environment, you can just use pip instead.

And that’s it! We are now ready to build a larger Flask application modularized using blueprints.

Working With Modules And Blueprints (Components)

Module Basics

We’ve now established our application structure and prepared its necessary dependencies. Our objective is to create reusable components within Flask, a process known as modularization.

One practical example is implementing an authentication system. By consolidating its views, controllers, models, and helpers in a single, logically organized location, you enable reusability. This approach not only facilitates efficient application maintenance but also boosts overall productivity.

Target example module (component) structure (inside /app):

# Our module example here is called *mod_auth*
# You can name them as you like as long as conventions are followed

/mod_auth
    |-- __init__.py
    |-- controllers.py
    |-- models.py
    |-- ..
    |-- .

Module Templates

To support modularizing to-the-max, we will structure the “templates” folder to follow the above convention and contain a new folder – with the same or a similar, related name as the module – to contain its template files.

Target example templates directory structure (inside LargeApp):

Creating The Application

In this section, we will continue on the previous steps and start with actual coding of our application before moving onto creating our first modularized component (using blueprints): mod_auth for handling all authentication related procedures (i.e. signing-in, signing-up, etc).

Edit “run.py” using nano

Place the contents:

Save and exit using CTRL+X and confirm with with Y.

Edit “config.py” using nano

Place the contents:

# Statement for enabling the development environment
DEBUG = True

# Define the application directory
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))  

# Define the database - we are working with
# SQLite for this example
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'app.db')
DATABASE_CONNECT_OPTIONS = {}

# Application threads. A common general assumption is
# using 2 per available processor cores - to handle
# incoming requests using one and performing background
# operations using the other.
THREADS_PER_PAGE = 2

# Enable protection agains *Cross-site Request Forgery (CSRF)*
CSRF_ENABLED     = True

# Use a secure, unique and absolutely secret key for
# signing the data. 
CSRF_SESSION_KEY = "secret"

# Secret key for signing cookies
SECRET_KEY = "secret"

Save and exit using CTRL+X and confirm with with Y.

Creating A Module / Component

Creating modules with Flask’s blueprints marks the initial and crucial step in our journey. In this section, we delve into the process of module creation.

What makes this approach truly remarkable is its emphasis on code portability and reusability, coupled with the simplicity it brings to the maintenance aspect. This ease of maintenance becomes particularly valuable down the road, sparing you the struggle of deciphering past decisions.

Step 1: Structuring The Module

As we have set out to do, let us create our first module’s (mod_auth) directories and files to start working on them.

After these operations, this is how the folder structure should look like:

Large Flask Applications system code

Step 2: Define The Module Data Model(s)

Place the below self-explanatory – exemplary – contents:

# Import the database object (db) from the main application module
# We will define this inside /app/__init__.py in the next sections.
from app import db

# Define a base model for other database tables to inherit
class Base(db.Model):

    __abstract__  = True

    id            = db.Column(db.Integer, primary_key=True)
    date_created  = db.Column(db.DateTime,  default=db.func.current_timestamp())
    date_modified = db.Column(db.DateTime,  default=db.func.current_timestamp(),
                                           onupdate=db.func.current_timestamp())

# Define a User model
class User(Base):

    __tablename__ = 'auth_user'

    # User Name
    name    = db.Column(db.String(128),  nullable=False)

    # Identification Data: email & password
    email    = db.Column(db.String(128),  nullable=False,
                                            unique=True)
    password = db.Column(db.String(192),  nullable=False)

    # Authorisation Data: role & status
    role     = db.Column(db.SmallInteger, nullable=False)
    status   = db.Column(db.SmallInteger, nullable=False)

    # New instance instantiation procedure
    def __init__(self, name, email, password):

        self.name     = name
        self.email    = email
        self.password = password

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

Save and exit using CTRL+X and confirm with with Y.

Step 3: Define Module Forms

Place the below self-explanatory – exemplary – contents:

Large Flask Applications

Save and exit using CTRL+X and confirm with with Y.

Step 4: Define Application Controllers (Views)

Place the below self-explanatory – exemplary – contents:

# Import flask dependencies
from flask import Blueprint, request, render_template, \
                  flash, g, session, redirect, url_for

# Import password / encryption helper tools
from werkzeug import check_password_hash, generate_password_hash

# Import the database object from the main app module
from app import db

# Import module forms
from app.mod_auth.forms import LoginForm

# Import module models (i.e. User)
from app.mod_auth.models import User

# Define the blueprint: 'auth', set its url prefix: app.url/auth
mod_auth = Blueprint('auth', __name__, url_prefix='/auth')

# Set the route and accepted methods
@mod_auth.route('/signin/', methods=['GET', 'POST'])
def signin():

    # If sign in form is submitted
    form = LoginForm(request.form)

    # Verify the sign in form
    if form.validate_on_submit():

        user = User.query.filter_by(email=form.email.data).first()

        if user and check_password_hash(user.password, form.password.data):

            session['user_id'] = user.id

            flash('Welcome %s' % user.name)

            return redirect(url_for('auth.home'))

        flash('Wrong email or password', 'error-message')

    return render_template("auth/signin.html", form=form)

Save and exit using CTRL+X and confirm with with Y.

Step 5: Set Up The Application in “app/init.py”

Place the contents:

# Import flask and template operators
from flask import Flask, render_template

# Import SQLAlchemy
from flask.ext.sqlalchemy import SQLAlchemy

# Define the WSGI application object
app = Flask(__name__)

# Configurations
app.config.from_object('config')

# Define the database object which is imported
# by modules and controllers
db = SQLAlchemy(app)

# Sample HTTP error handling
@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

# Import a module / component using its blueprint handler variable (mod_auth)
from app.mod_auth.controllers import mod_auth as auth_module

# Register blueprint(s)
app.register_blueprint(auth_module)
# app.register_blueprint(xyz_module)
# ..

# Build the database:
# This will create the database file using SQLAlchemy
db.create_all()

Save and exit using CTRL+X and confirm with with Y.

Step 6: Create The Templates

Applications code

Place the contents:

{% macro render_field(field, placeholder=None) %}
{% if field.errors %}
<div>
{% elif field.flags.error %}
<div>
{% else %}
<div>
{% endif %}
    {% set css_class = 'form-control ' + kwargs.pop('class', '') %}
    {{ field(class=css_class, placeholder=placeholder, **kwargs) }}
</div>
{% endmacro %}

<div>
  <div>
    <legend>Sign in</legend>
    {% with errors = get_flashed_messages(category_filter=["error"]) %}
    {% if errors %}
    <div>
    {% for error in errors %}
    {{ error }}<br>
    {% endfor %}
    </div>
    {% endif %}
    {% endwith %}

    {% if form.errors %}
    <div>
    {% for field, error in form.errors.items() %}
    {% for e in error %}
    {{ e }}<br>
    {% endfor %}
    {% endfor %}
    </div>
    {% endif %}
    <form method="POST" action="." accept-charset="UTF-8" role="form">
      {{ form.csrf_token }}
      {{ render_field(form.email, placeholder="Your Email Address",
                                  autofocus="") }}
      {{ render_field(form.password, placeholder="Password") }}
      <div>
      <label>
        <input type="checkbox" name="remember" value="1"> Remember Me
      </label>
      <a role="button" href="">Forgot your password?</a><span class="clearfix"></span>
      </div>
      <button type="submit" name="submit">Sign in</button>
    </form>  
  </div>
</div>

Save and exit using CTRL+X and confirm with with Y.

Step 7: See Your Module In Action

After having created our first module, it is time to see everything in action.

Run a development server using the run.py:

This will initiate a development (i.e. testing) server hosted at port 8080.

Visit the module by going to the URL:

Although you will not be able to login, you can see it in action by entering some exemplary data or by testing its validators.

Visited 1 times, 1 visit(s) today

Leave a comment

Your email address will not be published. Required fields are marked *