Flask configs per environment

When working on a Flask project, you may want to override flask configurations
on different environments. Here are some suggestions.

A folder structure like the following might work well

/demo/
     __init__.py
     configs/
             __init__.py
             application.id
             default.py
             development.py
             production.py
             staging.py
             test.py
     controllers.py
     templates/
               index.html

In this structure, configs are plain python files and default is always loaded.
It is then merged with the environment-specific configuration (e.g. development).

It helps if the flask application is instantiated by a factory method/function.
Here are some ways to select the environment, each with higher precendence
than the previous one.

  • read the contents of a file (in this example application.id)
  • pass an environment variable (e.g. APP_ENV)
  • Override with a variable (useful for testing)

    from os import path
    from flask import Flask, Blueprint
    from flask import current_app

    root = Blueprint(“root”, name)

    @root.route(“/”)
    def root_index():
    return “Hello from %s” % current_app.config.get(“MYCONFIG”)

    basepath = path.abspath(path.dirname(file))

    CONFIGS = “demo.configs”

    def config_object_for(override=None):

    if override:
        return ".".join([CONFIGS, override])
    
    from os import environ
    
    try:
        with open(path.join(basepath, 'configs/application.id')) as appid:
            env = appid.read().strip()
    except Exception, e:
        pass
    
    environment_variable = environ.get("APP_ENV")
    if environment_variable:
        env = environment_variable or "development"
    
    return ".".join([CONFIGS, env])
    

    def create_app(override=None):

    app = Flask(__name__)
    app.config.from_object(config_object_for('default'))
    app.config.from_object(config_object_for(override))
    app.register_blueprint(root)
    
    return app
    

    if name == ‘main‘:
    create_app().run(debug=True)