Flask Boilerplate

Reference codebase used in all Flask Web Applications provided by the AppSeed platform - features:

Links


What is Flask


Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. Classified as a microframework, Flask is written in Python and it does not require particular tools or libraries. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions.

Flask Links


Environment


To use the stater, Python3 should be installed properly in the workstation. If you are not sure if Python is properly installed, please open a terminal and type python --version. The full-list with dependencies and tools required to build the app:

  • Python3 - the programming language used to code the app
  • GIT - used to clone the source code from the Github repository
  • Basic development tools (g++ compiler, python development libraries ..etc) used by Python to compile the app dependencies in your environment.


Check Python version (using the terminal)

$ # Check Python version
$ python --version
Python 3.7.2 # <--- All good


Check GIT command tool (using the terminal)

$ # Check git
$ git --version
$ git version 2.10.1.windows.1 # <--- All good


For more information on how to set up your environment please access the resources listed below. In case we've missed something, contact us on Discord.


Build the app


To built and start the app locally, follow the steps:

Get the source code

  • Download the ZIP from Github Repository
  • Using GIT tool in the terminal to clone the source code

Change the current directory to source code directory

$ # Make sure you are running the commands INSIDE source code directory
$
$ # Create and activate a Virtualenv (Unix based systems)
$ virtualenv env
$ source env/bin/activate
$
$ # Create and activate a Virtualenv (Windows based systems)
$ # virtualenv env
$ # .\env\Scripts\activate
$
$ # Install requirements
$ pip3 install -r requirements.txt
$
$ # Set the FLASK_APP environment variable
$ (Unix/Mac) export FLASK_APP=run.py
$ (Windows) set FLASK_APP=run.py
$ (Powershell) $env:FLASK_APP = ".\run.py"
$
$ # Set up the DEBUG environment
$ # (Unix/Mac) export FLASK_ENV=development
$ # (Windows) set FLASK_ENV=development
$ # (Powershell) $env:FLASK_ENV = "development"
$
$ # Run the application
$ # --host=0.0.0.0 - expose the app on all network interfaces (default 127.0.0.1)
$ # --port=5000    - specify the app port (default 5000)  
$ flask run --host=0.0.0.0 --port=5000
$
$ # Access the app in browser: http://127.0.0.1:5000/

At this point, we can visit the app in the browser http://127.0.0.1:5000/. By default, the app will redirect guest users to the login page. To access the private pages:

  • Create a new user using the registration page
  • Authenticate using the login page


App Codebase (simplified)


Starter uses a simple codebase (no Blueprints) with a structure presented bellow:

< PROJECT ROOT >
   |
   |-- app/             # The actual APP
   |-- app/__init__.py  # App Constructor
   |
   |-- requirements.txt # App dependencies
   |
   |-- run.py           # App Bootstraper (returs the WSGI app)
   |
   |-- ***********************************


The bootstrap flow


  • run.py imports the WSGI Application from app directory
  • app/__init__.py is called and trigger the following actions:
    • invoke Flask Framework constructor
    • Read the configuration from app/config.py
    • Invoke SQLAlchemy
    • Invoke LoginManager exposed by Flask-Login


app/__init__.py (simplified version)

# File: /app/__init__.py

from flask            import Flask        # Import Flask
from flask_sqlalchemy import SQLAlchemy   # For ORM db access  
from flask_login      import LoginManager # Used for authentication

# Directive 1 - Inject Flask magic
app = Flask(__name__)

# Directive 2 - Load the configuraton from `app/config.py`
app.config.from_object('app.config.Config')

# Directive 3 - Flask-SqlAlchemy wrapping
db = SQLAlchemy  (app)

# Directive 4 - Invoke and init the login manager
lm = LoginManager( )
lm.init_app(app)

# Directive 5 - Setup database (create tables)
@app.before_first_request
def initialize_database():
    db.create_all()

# Directive 5 - Start the App
from app import views, models

# At this point we have a valid WSGI app


The app/__init__.py constructs the app by putting together a short-list of things:

  • Invoke Flask
  • Load the configuration from config.py
  • Invoke the SqlAlchemy ORM to handle the database content
  • Invoke and inject the Login Manager into the app
  • Check if the database tables are created
  • Finally, expose the app by importing views (app routing) and models (app tables)


App Codebase


The codebase structure is presented below:

< PROJECT ROOT >
   |
   |-- app/
   |    |-- __init__.py                   # App initializer
   |    |-- config.py                     # App configuration
   |    |-- forms.py                      # App Forms
   |    |-- models.py                     # App Models
   |    |-- util.py                       # Helpers
   |    |-- views.py                      # App Routing
   |    |
   |    |-- static/
   |    |    |-- <css, JS, images>         # CSS files, Javascripts files
   |    |
   |    |-- templates/
   |    |    |
   |    |    |-- includes/                 # Page chunks, components
   |    |    |    |
   |    |    |    |-- navigation.html      # Top bar
   |    |    |    |-- sidebar.html         # Left sidebar
   |    |    |    |-- scripts.html         # JS scripts common to all pages
   |    |    |    |-- footer.html          # The common footer
   |    |    |
   |    |    |-- layouts/                  # App Layouts (the master pages)
   |    |    |    |
   |    |    |    |-- base.html            # Used by common pages like index, UI
   |    |    |    |-- base-fullscreen.html # Used by auth pages (login, register)
   |    |    |
   |    |    |-- accounts/                 # Auth Pages (login, register)
   |    |    |    |
   |    |    |    |-- login.html           # Use layout `base-fullscreen.html`
   |    |    |    |-- register.html        # Use layout `base-fullscreen.html`  
   |    |    |
   |    |  index.html                      # The default page
   |    |  page-404.html                   # Error 404 page (page not found)
   |    |  page-500.html                   # Error 500 page (server error)
   |    |    *.html                        # All other pages provided by the UI Kit
   |
   |-- requirements.txt
   |
   |-- run.py
   |
   |-- ************************************************************************


App Configuration


The configuration file app/config.py specify a short-list with variables:

This configuration is loaded by app/__init__.py during the app initialization:

# File: /app/__init__.py

...

# Directive 2 - Load the configuraton from `app/config.py`
app.config.from_object('app.config.Config')

...


The default database is SQLite, configured by the SQLALCHEMY_DATABASE_URI variable:

# File: /app/config.py

...

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'db.sqlite3')
SQLALCHEMY_TRACK_MODIFICATIONS = False

...

The database and associated tables, defined in app/models.py are automatically created at the first request in the physical file specified in the configuration - default location app/db.sqlite3.

Hint: to visualize the SQLite database content an external tool should be installed: DB Browser for SQLite it might be a good choice.


App Tables


The file app/models.py defines the table(s) used by the application. Being a simple starter, by default the following tabes are defined:

  • Table #1 - User with fields:
    • Id - Primary key, unique
    • user - Store the username
    • email - The email address
    • password - Hashed password


App Forms


The file app/forms.py defines the table(s) used by the application. Being a simple starter, by default the following forms are defined:

  • Form #1 - LoginForm with fields:
    • username
    • password


  • Form #2 - RegisterForm with fields:
    • name - The friendly name
    • username - used to authenticate
    • password - used to authenticate
    • email


App Routing


The file app/views.py defines the application routing. Here is the list with defined paths and associated handlers


Route /login.html

The route handles the app authentication using a simple flow:

  • Loads LoginForm defined in app/forms.py
  • GET request
    • loads the page app/tempates/accounts/login.html
  • POST request
    • Validate the input data: username, password
    • Locate the user in the database
    • Verify the password against the database version
    • For success, authenticate the user
    • For errors, reload the login page and inform the user


Route /register.html

The route handles the app authentication using a simple flow:

  • Loads RegisterForm defined in app/forms.py
  • GET request
    • loads the page app/tempates/accounts/register.html
  • POST request
    • Validate the input data: username, password, email
    • Check if username or email is already registered
    • Hash the password provided by the user
    • Save the user in the database
    • Reload the registration page and inform the user


Route /logout.html

The route delete the user session and redirect the user to the login.html


Default Route /

The route will serve all pages defined in the app/templates for the authenticated users using a simple flow:

  • Check user is authenticated
  • Redirect to /login.html guests users
  • Load the requested page from app/templates folder
  • Return Error 404 and associated page if requested page cannot be located
  • Return Error 500 if a critical error occurred during the page load


Pages & Assets


Pages served by the starter are organized using a simple folder structure:

< PROJECT ROOT >
   |
   |-- app/
   |    |
   |    |-- static/assets/
   |    |    |-- <css, JS, images>         # CSS files, Javascripts files
   |    |
   |    |-- templates/
   |    |    |
   |    |    |-- includes/                 # Page chunks, components
   |    |    |    |
   |    |    |    |-- navigation.html      # Top bar
   |    |    |    |-- sidebar.html         # Left sidebar
   |    |    |    |-- scripts.html         # JS scripts common to all pages
   |    |    |    |-- footer.html          # The common footer
   |    |    |
   |    |    |-- layouts/                  # App Layouts (the master pages)
   |    |    |    |
   |    |    |    |-- base.html            # Used by common pages like index, UI
   |    |    |    |-- base-fullscreen.html # Used by auth pages (login, register)
   |    |    |
   |    |    |-- accounts/                 # Auth Pages (login, register)
   |    |    |    |
   |    |    |    |-- login.html           # Use layout `base-fullscreen.html`
   |    |    |    |-- register.html        # Use layout `base-fullscreen.html`  
   |    |    |
   |    |  index.html                      # The default page
   |    |  page-404.html                   # Error 404 page (page not found)
   |    |  page-500.html                   # Error 500 page (server error)
   |    |    *.html                        # All other pages provided by the UI Kit
   |
   |
   |-- ************************************************************************


Static Assets

The folder contains the assets provided by the UI Kit integrated into the app. AppSeed conversion scripts will modify the original UI kit path to match the structure:

  • static/assets - the root directory for all files (JS, images)
  • static/assets/css - CSS files that style the app
  • static/assets/img - Images and Icons
  • static/assets/js - javascript files provided by the UI Kit
  • static/assets/scss - SCSS files, if provided by the UI Kit vendor


Templates Folder

All pages served by the application are located inside this folder.

  • templates/layouts - the directory with app masterpages
  • templates/includes - the directory with HTML chunks and components
  • templates/accounts - store the authentication pages (login, registration)
  • templates/ - all pages defined/served by the app are saved in the root of the templates folder


Common pages

This section lists the common pages defined in all Flask applications prototyped on top of this generic starter.

  • login.html, rendered with layouts/base-fullscreen.html
  • register.html, rendered with layouts/base-fullscreen.html
  • index.html, rendered with layouts/base.html
  • page-404.html, rendered with layouts/base.html
  • page-403.html, rendered with layouts/base.html


Data Structures


The Flask starter exposes a short-list with data structures used globally across the app:


current_user object

Constructed by Flask-Login can be used to detect if the current request is executed by an authenticated user or not. The object has global visibility and can be used in all app controllers and handlers but also in views.


How it works

app/views.py define a callback function required by Flask-Login library:

# File: app/views.py

# *****************************************
# `lm` is constructed in `app/__init__.py`
#
# lm = LoginManager(   ) # flask-loginmanager
# lm.init_app(app)       # init the login manager
#
# *****************************************
#
# provide login manager with load_user callback
@lm.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


Usage in contoler

# File: app/views.py

def index(path):

    # Redirect guests users to login page
    if not current_user.is_authenticated:
        return redirect(url_for('login'))


Usage in view

    <div class="collapse navbar-collapse" id="navigation">
        <ul class="navbar-nav ml-auto">

        <!-- The Usage of <current_user> object -->
        {% if current_user.is_authenticated %}

            <!-- Html chunk rendered for authenticated users-->

            <li class="nav-item">
                <a href="/" class="nav-link text-primary">
                    <i class="tim-icons icon-minimal-left"></i> Back to Dashboard
                </a>
            </li>

        {% else %}

            <!-- Html chunk rendered for guests users-->

            <li class="nav-item ">
                <a href="{{ url_for('register') }}" class="nav-link">
                    <i class="tim-icons icon-laptop"></i> Register
                </a>
            </li>
            <li class="nav-item ">
                <a href="{{ url_for('login') }}" class="nav-link">
                    <i class="tim-icons icon-single-02"></i> Login
                </a>
            </li>

        {% endif %}

        </ul>
    </div>


Flask Apps that use this starter


For full-index please access Github or the dedicated page Flask Apps hosted by AppSeed.


Flask resources