Utilizing classes to create readable and maintainable project code with Python and Flask.

Given the freedom that Flask gives a developer, it’s very easy to create an application structure that leads to unmaintainable and unreadable code. I have found a structure that works for me when it comes to Flask projects, which keeps your project readable, testable, and maintainable — with very well defined entry points. When starting a project, define a folder structure as such:

/project

/app

/lib

/database

mysql.py

mongo.py

/queue

rabbit.py

/models

model.py

/config

config.py

development.json

production.json

test.json

/controllers

controller_a.py

controller_b.py

/static

/templates

main.py

Our main.py is actually our route file, but also acts as an initializer for objects that we want to pass around. The main.py file would look as follows:

from flask import Flask from app.controllers.controller_a import ControllerA

from app.controllers.controller_b import ControllerB

from app.lib.config import Config

from app.lib.database import MySQL

from app.lib.queue import Rabbit if __name__ == ‘__main__’:

app = Flask(__name__) # load libs

Config = Config(os.environ['APP_ENVIRONMENT'])

MySQL = MySQL(Config.mysql)

Rabbit = Rabbit(Config.rabbit) # controllers

ControllerA = ControllerA(Config, MySQL, Rabbit)

ControllerB = ControllerB(Config, MySQL, Rabbit) # Define our routes below # handle interaction with the homepage and login/signup pages

app.add_url_rule(‘/’, ‘home’,

ControllerA.index, methods=[‘GET’])

app.add_url_rule(‘/signup’, ‘signup’,

ControllerA.signup, methods=[‘GET’, ‘POST’])

app.add_url_rule(‘/login’, ‘login’,

ControllerA.signin, methods=[‘GET’, ‘POST’]) # handle post interaction

app.add_url_rule(‘/posts’, ‘posts’, ControllerB.posts,

methods=[‘GET’, ‘POST’, ‘PUT’, ‘DELETE’])

app.add_url_rule(‘/posts/<int:post_id>’, ‘posts’,

ControllerB.posts, methods=[‘GET’]) app.run(host=Config.host, port=Config.port, debug=Config.debug)

This way, there’s no need to apply decorators to the methods defined in the controller, as it’s simply a class that’s being called:

class ControllerA

def __init__(self):

pass def index(self):

pass def signup(self):

pass def signin(self):

pass def posts(self):

pass

While I have not explored the performance implications of this setup vs a more traditional setup, I can only imagine that not spinning up multiple objects per request, but having one set of objects warmed and ready to run would be far more advantageous performance-wise. Not only that, but your methods are now testable as well.

Would be interested in hearing what project structure you use, or your thoughts on this particular structure!