Application Factories

If you are already using packages and blueprints for your application(Modular Applications with Blueprints) there are a couple of really nice ways to further improvethe experience. A common pattern is creating the application object whenthe blueprint is imported. But if you move the creation of this objectinto a function, you can then create multiple instances of this app later.

So why would you want to do this?

  • Testing. You can have instances of the application with differentsettings to test every case.

  • Multiple instances. Imagine you want to run different versions of thesame application. Of course you could have multiple instances withdifferent configs set up in your webserver, but if you use factories,you can have multiple instances of the same application running in thesame application process which can be handy.

So how would you then actually implement that?

Basic Factories

The idea is to set up the application in a function. Like this:

  1. def create_app(config_filename):
  2. app = Flask(__name__)
  3. app.config.from_pyfile(config_filename)
  4.  
  5. from yourapplication.model import db
  6. db.init_app(app)
  7.  
  8. from yourapplication.views.admin import admin
  9. from yourapplication.views.frontend import frontend
  10. app.register_blueprint(admin)
  11. app.register_blueprint(frontend)
  12.  
  13. return app

The downside is that you cannot use the application object in the blueprintsat import time. You can however use it from within a request. How do youget access to the application with the config? Usecurrent_app:

  1. from flask import current_app, Blueprint, render_template
  2. admin = Blueprint('admin', __name__, url_prefix='/admin')
  3.  
  4. @admin.route('/')
  5. def index():
  6. return render_template(current_app.config['INDEX_TEMPLATE'])

Here we look up the name of a template in the config.

Factories & Extensions

It’s preferable to create your extensions and app factories so that theextension object does not initially get bound to the application.

Using Flask-SQLAlchemy,as an example, you should not do something along those lines:

  1. def create_app(config_filename):
  2. app = Flask(__name__)
  3. app.config.from_pyfile(config_filename)
  4.  
  5. db = SQLAlchemy(app)

But, rather, in model.py (or equivalent):

  1. db = SQLAlchemy()

and in your application.py (or equivalent):

  1. def create_app(config_filename):
  2. app = Flask(__name__)
  3. app.config.from_pyfile(config_filename)
  4.  
  5. from yourapplication.model import db
  6. db.init_app(app)

Using this design pattern, no application-specific state is stored on theextension object, so one extension object can be used for multiple apps.For more information about the design of extensions refer to Flask Extension Development.

Using Applications

To run such an application, you can use the flask command:

  1. $ export FLASK_APP=myapp
  2. $ flask run

Flask will automatically detect the factory (create_app or make_app)in myapp. You can also pass arguments to the factory like this:

  1. $ export FLASK_APP="myapp:create_app('dev')"
  2. $ flask run

Then the create_app factory in myapp is called with the string'dev' as the argument. See Command Line Interface for more detail.

Factory Improvements

The factory function above is not very clever, but you can improve it.The following changes are straightforward to implement:

  • Make it possible to pass in configuration values for unit tests so thatyou don’t have to create config files on the filesystem.

  • Call a function from a blueprint when the application is setting up sothat you have a place to modify attributes of the application (likehooking in before/after request handlers etc.)

  • Add in WSGI middlewares when the application is being created if necessary.