| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | Application Factories
 | 
					
						
							|  |  |  | =====================
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-18 02:27:25 +08:00
										 |  |  | If you are already using packages and blueprints for your application
 | 
					
						
							| 
									
										
										
										
											2020-04-05 03:57:14 +08:00
										 |  |  | (:doc:`/blueprints`) there are a couple of really nice ways to further improve
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | the experience.  A common pattern is creating the application object when
 | 
					
						
							| 
									
										
										
										
											2016-12-19 21:37:34 +08:00
										 |  |  | the blueprint is imported.  But if you move the creation of this object
 | 
					
						
							| 
									
										
										
										
											2015-12-03 17:51:24 +08:00
										 |  |  | into a function, you can then create multiple instances of this app later.
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | So why would you want to do this?
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1.  Testing.  You can have instances of the application with different
 | 
					
						
							|  |  |  |     settings to test every case.
 | 
					
						
							|  |  |  | 2.  Multiple instances.  Imagine you want to run different versions of the
 | 
					
						
							|  |  |  |     same application.  Of course you could have multiple instances with
 | 
					
						
							|  |  |  |     different configs set up in your webserver, but if you use factories,
 | 
					
						
							|  |  |  |     you can have multiple instances of the same application running in the
 | 
					
						
							|  |  |  |     same 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::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_app(config_filename):
 | 
					
						
							|  |  |  |         app = Flask(__name__)
 | 
					
						
							|  |  |  |         app.config.from_pyfile(config_filename)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-16 18:13:07 +08:00
										 |  |  |         from yourapplication.model import db
 | 
					
						
							|  |  |  |         db.init_app(app)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  |         from yourapplication.views.admin import admin
 | 
					
						
							|  |  |  |         from yourapplication.views.frontend import frontend
 | 
					
						
							| 
									
										
										
										
											2011-06-18 03:58:03 +08:00
										 |  |  |         app.register_blueprint(admin)
 | 
					
						
							|  |  |  |         app.register_blueprint(frontend)
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return app
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-18 03:58:03 +08:00
										 |  |  | The downside is that you cannot use the application object in the blueprints
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | at import time.  You can however use it from within a request.  How do you
 | 
					
						
							| 
									
										
										
										
											2011-06-16 22:28:51 +08:00
										 |  |  | get access to the application with the config?  Use
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | :data:`~flask.current_app`::
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-18 03:58:03 +08:00
										 |  |  |     from flask import current_app, Blueprint, render_template
 | 
					
						
							|  |  |  |     admin = Blueprint('admin', __name__, url_prefix='/admin')
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @admin.route('/')
 | 
					
						
							|  |  |  |     def index():
 | 
					
						
							|  |  |  |         return render_template(current_app.config['INDEX_TEMPLATE'])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here we look up the name of a template in the config.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-11 20:39:46 +08:00
										 |  |  | Factories & Extensions
 | 
					
						
							|  |  |  | ----------------------
 | 
					
						
							| 
									
										
										
										
											2013-03-16 18:13:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-11 20:39:46 +08:00
										 |  |  | It's preferable to create your extensions and app factories so that the
 | 
					
						
							|  |  |  | extension object does not initially get bound to the application.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 06:37:51 +08:00
										 |  |  | Using `Flask-SQLAlchemy <https://flask-sqlalchemy.palletsprojects.com/>`_,
 | 
					
						
							| 
									
										
										
										
											2014-02-09 21:35:38 +08:00
										 |  |  | as an example, you should not do something along those lines::
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:45:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-11 20:39:46 +08:00
										 |  |  |     def create_app(config_filename):
 | 
					
						
							|  |  |  |         app = Flask(__name__)
 | 
					
						
							|  |  |  |         app.config.from_pyfile(config_filename)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         db = SQLAlchemy(app)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | But, rather, in model.py (or equivalent)::
 | 
					
						
							| 
									
										
										
										
											2013-03-16 18:13:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     db = SQLAlchemy()
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:45:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-11 20:39:46 +08:00
										 |  |  | and in your application.py (or equivalent)::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_app(config_filename):
 | 
					
						
							|  |  |  |         app = Flask(__name__)
 | 
					
						
							|  |  |  |         app.config.from_pyfile(config_filename)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from yourapplication.model import db
 | 
					
						
							|  |  |  |         db.init_app(app)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Using this design pattern, no application-specific state is stored on the
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:45:22 +08:00
										 |  |  | extension object, so one extension object can be used for multiple apps.
 | 
					
						
							| 
									
										
										
										
											2013-10-11 20:39:46 +08:00
										 |  |  | For more information about the design of extensions refer to :doc:`/extensiondev`.
 | 
					
						
							| 
									
										
										
										
											2013-03-16 18:13:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | Using Applications
 | 
					
						
							|  |  |  | ------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 05:08:37 +08:00
										 |  |  | To run such an application, you can use the :command:`flask` command:
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 00:26:26 +08:00
										 |  |  | .. code-block:: text
 | 
					
						
							| 
									
										
										
										
											2020-10-16 05:08:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-02 23:43:02 +08:00
										 |  |  |     $ flask --app hello run
 | 
					
						
							| 
									
										
										
										
											2020-10-16 05:08:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 00:26:26 +08:00
										 |  |  | Flask will automatically detect the factory if it is named
 | 
					
						
							|  |  |  | ``create_app`` or ``make_app`` in ``hello``. You can also pass arguments
 | 
					
						
							|  |  |  | to the factory like this:
 | 
					
						
							| 
									
										
										
										
											2020-10-16 05:08:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 00:26:26 +08:00
										 |  |  | .. code-block:: text
 | 
					
						
							| 
									
										
										
										
											2020-10-16 05:08:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 03:20:27 +08:00
										 |  |  |     $ flask --app hello:create_app(local_auth=True) run
 | 
					
						
							| 
									
										
										
										
											2022-01-11 20:59:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 00:26:26 +08:00
										 |  |  | Then the ``create_app`` factory in ``myapp`` is called with the keyword
 | 
					
						
							|  |  |  | argument ``local_auth=True``. See :doc:`/cli` for more detail.
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Factory Improvements
 | 
					
						
							|  |  |  | --------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-20 03:32:47 +08:00
										 |  |  | The factory function above is not very clever, but you can improve it.
 | 
					
						
							|  |  |  | The following changes are straightforward to implement:
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-20 03:32:47 +08:00
										 |  |  | 1.  Make it possible to pass in configuration values for unit tests so that
 | 
					
						
							|  |  |  |     you don't have to create config files on the filesystem.
 | 
					
						
							|  |  |  | 2.  Call a function from a blueprint when the application is setting up so
 | 
					
						
							| 
									
										
										
										
											2010-05-27 23:55:57 +08:00
										 |  |  |     that you have a place to modify attributes of the application (like
 | 
					
						
							| 
									
										
										
										
											2017-10-20 03:32:47 +08:00
										 |  |  |     hooking in before/after request handlers etc.)
 | 
					
						
							|  |  |  | 3.  Add in WSGI middlewares when the application is being created if necessary.
 |