Home

Awesome

flask-template

Introduction

Flask is one of the popular web development frameworks available within the Python domain alongside with others such as Django and Tornado. I personally prefer it over the others because it offers a minimalist approach. It comes with very basic wrappers and helper packages, and you can chose to install specific bits of the puzzle as you develop your project and figure out what you need.

Recently, Flask's developer, Miguel Grinberg, released a github project where he showcased a very useful way to structure flask based web applications. The project is flasky.

I was influenced by flasky, and wanted to create and share a template based on flask which can be used for quickly creating flask applications. I made some minor changes to the original flasky's project structure, and also decided to use a different database and docker setup, which in my opinion, is more oriented towards commercial web development.

I created a very basic short stories web application, which is more of a template rather than a proper full on web application. It allows users to create, view and edit short stories through an API and also through a very basic HTML based web page.

The following guide provides insights on how the bits and pieces of the project work, and hopefully is not too complicated so that even a beginner python developer can follow it.


Project Setup

First Steps

You can begin by either downloading a zip file of the project through github, or using a git command to clone the project by:

git clone https://github.com/alisezer/flask-template.git

Virtual Environment Setup

It is preferred to create a virtual environment per project, rather then installing all dependencies of each of your projects system wide. Once you install virtual env, and move to your projects directory through your terminal, you can set up a virtual env with:

virtualenv venv -p python3.6

This will create a python3.6 based virtual environment (venv) for you within your projects directory.

Note: You need to have Python 3.6 installed on your local device.

Dependency installations

To install the necessary packages:

source venv/bin/activate
pip install -r requirements.txt

This will install the required packages within your venv.

The Makefile

When you are in the project directory on your terminal, you can use the make command for various options such as generating a new requirements.txt file, installing requirements on your venv or cleaning old compiled python .pyc files.

Try it out by entering the make command, which will show you available options.

.ENV File

The .env file holds your project specific settings such as your DB host name. These settings are better kept secret in most cases, therefore .env file is never committed to git. You will need to create a .env file, which can easily be created using the .env.template. Just run a simple copying command:

cp .env.template .env

and your .env file should be ready to be configured.

Variables in the .env file and their meanings:

The configurations are carried to code through the decouple library, which IMO provides a better solution compared to the traditional python-dotenv library.


Project Structure

Main Modules

Every flask application has a top-level module for creating the app itself, in this case, this module is the stories.py. This contains the flask application, and is used by other services such as Gunicorn or Flask's CLI while serving the application.

The stories.py module relies on the config.py and the app/__init__.py modules. It uses one of the configs specified in the .env file to create an application through the create_app method, which is placed under the __init__.py module.

app/__init__.py ties the necessary packages such as your SQLAlchemy or Migrations wrappers to your app, and provides a nice function for generating an application with a pre-specified config.

config.py hold multiple configuration files, which can be used in different scenarios such as testing vs production.

Models

The models, which are your database objects, are handled through SQLAlchemy's ORM. Flask provides a wrapper around the traditional SQLAlchemy package, which is used through out this project.

The models created are similar to your regular Python classes. They are inherited from pre-specified SQLAlchemy classes to make database table creation processes easier. These models can be found under the app/models folder.

In some projects, models can be handled within only one module, however in my opinion, it makes things easier when you handle them in multiple modules (one module per model).

If you want to create more models in your application, you can simply create modules under this folder, and later on tie them back to your app.

API

The project creates a simple API which has 4 endpoints for retrieving, creating and editing stories. The API is structured by using Flask's blueprint functionality.

api/stories.py module creates the endpoints, where the api/__init__.py creates the blueprint for API formation.

The blueprint object is later on imported and tied to the app in the app/__init__.py module.

Main APP (Web Page)

The project also creates a very simple web page for viewing and creating stories. The flow for this logic is handled under the app/main folder. forms.py basically creates a very simple web form for creating a story, while the views are handled in the views.py module.

Like the API, the web page relies on a blueprint, which is initiated in the __init__.py module.

The HTML and Static files for CSS required for rendering and styling web pages can be found under the templates and static folder. (Although there is nothing in the static folder at the moment)

Logging

Logging is handled through flask's logger. However, custom handlers for logging are created under the app/utils/logging.py module, which are tied to application when initiated with the docker config. (Can be found under the config.py module.)

The rotating handler creates rotating logs under the logs folder, while the stream handler logs to the terminal/client. Other logger handlers can be placed here such as an SMTP logger (for emailing errors).


Database Choice & Operations

Usually for smaller projects, databases such as SQLite is preferred for the ease of use. However, in most of the production environments, these databases are never used so learning how to set them up might be useless for larger commercial projects.

Keeping this in mind, even though the project is quite small, I went the extra mile to setup a proper PostgreSQL database. The configurations for this database is specified under the .env file, and it is set as the default database.

Python uses psycopg2 driver to connect to postgres databases. It quite easy to install psycopg2 on Linux based OS, however you may need to get Homebrew on your Mac to make your installation easier for you.

Setting up a Postgres Database

Assuming that you have installed postgres database (if you haven't Homebrew is the way I prefer for installations on Mac, and with Ubuntu, its even easier), you can easily setup a database through your terminal.

After reaching the postgres terminal through a PSQL command such as

sudo -u postgres psql

You can create a new user and make the user a superuser for your project by

create user tester with password 'password';
alter user tester superuser;

(Making the user a superuser makes things easier when creating tables or databases)

And then create a database and grant privileges locally by

create database stories;
grant all privileges on database stories to tester;

Granting privileges allows your user to make changes to your database.

Make sure you save these information, and add them to your .env file so your code can make changes to the database

On your .env file, you will want to set your database_host variable to localhost, and probably your database will be operating on port (database_port) 5432 unless specified otherwise.

For this case, your database_name will be stories, database_user will be tester and database_password will be password.

This should do it with the database setup!

Migrations

Database migrations are handled through Flask's Migrate Package, which provides a wrapper around Alembic. Migrations are done for updating and creating necessary tables/entries in your database. Flask provides a neat way of handling these.

After exporting your flask CLI to point towards your application (for example in this case it can be done with):

export FLASK_APP=stories.py

You can find the necessary database commands with:

flask db

Initially, if you were to create an app from scratch, you would need to initiate your migrations with:

flask db init

In this case migrations folder is already there. So, you won't have to initiate it. Once you start altering your models, you will need to create a new migrations scripts. For example, if you add or remove fields from the existing models or create new models you would need to generate new migrations and update your database.

For generating new migrations, you can use:

flask db migrate

And for applying your new migrations to your database, you can use:

flask db upgrade

The project also creates a shortcut for upgrading, which is added to Flask's CLI:

flask deploy

Running the Application

Once you have setup your database, you are ready to run the application. Assuming that you have exported your app's path by:

export FLASK_APP=stories.py

You can go ahead and run the application with a simple command:

flask run

You can also run your app using Gunicorn, which a separate WSGI Server that plays very well with Flask:

gunicorn --reload stories:app

Docker Setup

The project also has docker functionality, which means if you have docker installed on your computer, you can run it using Docker as well!

Docker creates containers for you, and basically serves your application using these containers. The necessary setting files for the docker setup can be found under docker-compose.yaml and Dockerfile it self.

In this case, docker uses a prebuilt Python3.6 image that runs on Ubuntu, and creates Nginx reverse proxy and Postgres database containers to serve the application.

To build the docker image, fist, set your ENV variable within your .env file to docker.

And then, run:

sudo docker-compose up --build

Once its built, it will do the necessary migrations for your application, and your app will be running straight away. You do not need to specify the --build command a second time to run the docker compose instance:

sudo docker-compose up

Docker becomes especially useful while deploying your applications on servers, and makes the DevOps easier. You can read more about docker.


Finally

Hope this guide/template comes useful to you! If you have any feedback good or bad, please do let me know or feel free to fork and raise a PR. Would be happy to discuss possible improvements. Also, I have tried to leave useful comments within the code it self, so further explanation to what each module does can be found within the comments and docstrings.

Acknowledgements

Many thanks to Jose Rivera-Rubio for his help with the docker setup!

Todo and Improvements

  1. Add tests