The most straightforward way to create a Flask application is to create a global Flask instance […]. While this is simple and useful in some cases, it can cause some tricky issues as the project grows.
But why bother? It has to do with how Python loads modules. Let’s take a file creatively called
print("global") def func(): print("local")
Python 3.7.0 >>> from file import func global >>> func() local
Oops. When I tried to import the function in an interactive session, the
This function creating the Flask application is called the application factory. (It’s an awful name, but naming stuff is hard. Factory methods are a thing in object-oriented programming, and this is kind of analogous.)
Simple, right? The tricky part is be figuring out how to hook Flask extensions up. We know this is bad, but this is easy to initialise:
# __init__.py app = Flask(__name__) # configuration of app here # (have to use environmental variable or something?) # models.py db = SQLAlchemy(app)
app is created inside a function, how can
db use it?
All extensions include an
init_app method for the application factory pattern. It’s going to look more complicated, but it’s worth it:
# __init__.py def create_app(debug=True): app = Flask(__name__) # configuration of app here, can use `debug`, yay! from .models import db db.init_app(app) return app # models.py db = SQLAlchemy()
Despite the name, application factories aren’t that complicated, and the documentation has improved significantly since 2016. It’s much easier to start with an application factory than try and reorganise a project later, so I’d recommend it from day one.
The application factory pattern makes configuration easy, as well as helping to avoid circular imports. Because imports can be performed when the app is created, this is an inversion of the usual import order. Instead of
app being imported by everything, everything (extensions, models, views/blueprints) is imported by the factory and bound together. Speaking of blueprints…
In a normal project, the number of views, and templates, and models, and forms, etc. will grow. You can (hackily) separate them out, but wouldn’t it be nice to have something that groups related views, templates, models, and forms? Blueprints! They are a great way to modularly compose Flask applications, which will help scale up projects.
The documentation on blueprints is pretty good, and they’re very analogous to views, so I’m brazenly going to gloss over that. But let it be said that refactoring an application to use blueprints is hard. So the upfront time investment is worth it, and along with application factories, I do it even for small proof of concept projects.