What is the Flask application factory pattern and why should you use it?
The application factory pattern creates the Flask app inside a function rather than as a module-level global. This function typically:
- Creates the Flask instance
- Loads configuration
- Initializes extensions (db, login manager, etc.)
- Registers blueprints
- Returns the configured app
Why use it:
- Testing: Create separate app instances with different configs (testing vs production)
- Multiple instances: Run different configurations simultaneously
- Circular imports: Avoids issues where extensions need the app at import time
- Blueprints: Clean separation of concerns
- Flask CLI: Works better with the
flaskcommand
def create_app(config=None):
app = Flask(__name__)
app.config.from_object(default_config)
if config:
app.config.update(config)
init_extensions(app)
register_blueprints(app)
return app
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# Extensions created without app (initialized later)
db = SQLAlchemy()
migrate = Migrate()
def create_app(config=None):
"""Application factory."""
app = Flask(__name__)
# Default configuration
app.config.from_mapping(
SECRET_KEY='dev-secret-key',
SQLALCHEMY_DATABASE_URI='sqlite:///app.db',
SQLALCHEMY_TRACK_MODIFICATIONS=False,
)
# Override with passed config (useful for testing)
if config:
app.config.update(config)
# Initialize extensions with app
db.init_app(app)
migrate.init_app(app, db)
# Register blueprints
from .routes.auth import auth_bp
from .routes.api import api_bp
app.register_blueprint(auth_bp)
app.register_blueprint(api_bp, url_prefix='/api')
# Register error handlers
@app.errorhandler(404)
def not_found(error):
return {'error': 'Not found'}, 404
@app.errorhandler(500)
def server_error(error):
return {'error': 'Internal server error'}, 500
return app
# Usage in production (wsgi.py or app.py)
app = create_app()
# Usage in tests
def test_config():
app = create_app({
'TESTING': True,
'SQLALCHEMY_DATABASE_URI': 'sqlite:///:memory:',
})
assert app.config['TESTING'] is True
# Usage with Flask CLI
# In pyproject.toml or .flaskenv:
# FLASK_APP=mypackage:create_app
- •Create Flask app inside a function, not at module level
- •Extensions are created globally but initialized with init_app() inside the factory
- •Enables different configs for testing, development, production
- •Avoids circular import issues
- •Extensions must support the init_app pattern (most Flask extensions do)
- •Importing the app directly from the module does not work -- use current_app instead
- •Blueprint imports should be inside the factory to avoid circular imports
- •Flask CLI needs FLASK_APP pointing to the factory function