3 Comments

Refactoring a Flask App with Blueprints

I recently worked on a legacy Flask app that was in need of refactoring. We were unfamiliar with a lot of the codebase, and we had a monolithic server.py with over a hundred routes. Using Flask’s blueprints, we were able to break the app into logical segments and gain familiarity with the codebase.

As a Flask app ages, having over a hundred endpoints is not uncommon. For example, you might find 100+ @app.route() calls in the main Flask file. The functionality of each of the routes might be in the main file or split off in modules. Ideally, we would be able to break out the route declarations along with the functionality of that route.

Blueprints offer us the ability to separate a unit of functionality from the main Flask app. Blueprints can be reused across applications or multiple times within one application.

I’ll go over the most basic example of how to use a blueprint. Let’s split off a render function used for one page of the application. We’ll set up a new file and get a new blueprint instance. Any calls that you would have previously made on app, you will now make on the blueprint. Back in your main app file, you’ll now import and register the blueprint. By passing url_prefix, you will apply a prefix to all routes set up in that blueprint.

#-----blueprints/simple_templates.py-----
from flask import Blueprint, render_template

simple_templates = Blueprint('simple_templates', __name__)

@simple_templates.route("/faq")
def faq():
    return render_template('faq.html')


#-----server.py-----
from flask import Flask
from blueprints.simple_templates import simple_templates

app = Flask(__name__)
app.register_blueprint(simple_templates)

Another way to use a blueprint is to repeat a common pattern. One blueprint can be registered multiple times. For example, you could abstract a common blueprint for CRUD and reuse it across multiple models. You can also use the static_folder and template_folder options when registering a blueprint to specialize it for reuse.

One of the biggest problems I encountered when refactoring with blueprints is that I needed access to a running instance of the app. There are two ways to solve this. You could try refactoring out the use of the running app into a different section of the app–but this solution won’t always work.

The other solution is to use current_app, which can be imported from Flask. You can use this any place where you would have used a reference to app.

There’s a a lot more to blueprints that I didn’t cover, and you can find out more at the docs here:

Modular Applications with Blueprints — Flask 0.12.4 documentation
API — Flask 0.12.4 documentation