Growing your Flask App - Blueprints

Posted by Arthur Barros on October 29, 2015

If you didn’t read the previous post about this topic, please go ahead to Growing your Flask App - Folder Structure

The simplest way I found so far to organize my Flask apps is to using the HMVC pattern. The concept is really easy to get used to, but it can be trick to implement with your Flask application because of the poor official documentation.

Mapping the modules folder

Refactor your __init__.py at the root of your app, and use the register_blueprint which is builtin to the flask.blueprint object.

app_name/webapp/__init__.py

 from flask import Flask
 import modules.home.routes
 app = Flask(__name__)
 app.register_blueprint(modules.home.routes.blueprint)

Everytime we create a new module we have to import it and register the Blueprint object to the app instance. So our application become aware of the new module.

Mapping our routes to the module controller’s a.k.a routes.py

Each of our modules should have a mandatory routes.py file, responsible to map each route of your app to the matching controller. To solve it we are going to import our module controller relative to our routes.py and than initiate a new Blueprint instance.

app_name/webapp/modules/home/routes.py

 from flask import Blueprint
 import controller
 blueprint = Blueprint("home", __name__, url_prefix='/', template_folder='templates')
 blueprint.route("/", methods=["GET"])(controller.index)

At the 4th line, we are creating a new instance of the Blueprint class, the first argument, is the module name which we are going to use when referencing our modules using the url_for() method.

url_prefix is used to proper name your modules to the url, for example url_prefix='account' would give us the following url path to our module http://url/account/<controller

template_folder it takes the relative path to the routes.py file to look for our templates we are going to use with the controller we assined to. Everytime our controller.index method tries to resolve a template to render with render_temapltemethod it will look this to the teamplte_folder path under our module, and if it don’t find any matching file it will look at the app_name/webapp/templates for a matching.

Be aware with you have multiple template files with the same name under different modules it WILL resolve the first one it finds, no matter what module it is, this is a known issue by the time i write this post

At the 5th line, we are assinging our routes with the proper http method it handle to the method reponsible to solve it.

blueprint.route the first argument is the name will be assigned to the controller method, for example blueprint.route("magic_the_gathering", methods=["GET"])(controller.index) will result in the following uri http://url/account/magic_the_gathering

Conclusion

With this approach you can start to grow your application and spread the responsabillity to your business model accros differente modules and view. It improves the quallity of your project and we start to see some single responsibility principle pattern