Ep.12 Flask configuration files

Flask configuration files | Learning Flask Ep. 12

Configuring Flask applications using a config file and classes

Configuration is an important part of any appliction and Flask provides several different methods for us to configure our app.

In this part of the “Learning Flask” series, we’re going to cover our preferred app configuration method, using a config file with classes.

Let’s get started.

Config basics

Every Flask application has a global config object which can be accessed via app.config.

Flask’s config object allows us to assign values to configuration variables, which we’ll then have access to throughout our application.

The global config object can be treated just like a Python dictionary, which we can access and modify.

The best way to visually see the config object it to simply print it in one of your routes. Go ahead and add the following to any route:

print(app.config)

You’ll see:

{'APPLICATION_ROOT': '/',
 'DEBUG': True,
 'ENV': 'development',
 'EXPLAIN_TEMPLATE_LOADING': False,
 'JSONIFY_MIMETYPE': 'application/json',
 'JSONIFY_PRETTYPRINT_REGULAR': False,
 'JSON_AS_ASCII': True,
 'JSON_SORT_KEYS': True,
 'MAX_CONTENT_LENGTH': None,
 'MAX_COOKIE_SIZE': 4093,
 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(days=31),
 'PREFERRED_URL_SCHEME': 'http',
 'PRESERVE_CONTEXT_ON_EXCEPTION': None,
 'PROPAGATE_EXCEPTIONS': None,
 'SECRET_KEY': None,
 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(seconds=43200),
 'SERVER_NAME': None,
 'SESSION_COOKIE_DOMAIN': None,
 'SESSION_COOKIE_HTTPONLY': True,
 'SESSION_COOKIE_NAME': 'session',
 'SESSION_COOKIE_PATH': None,
 'SESSION_COOKIE_SAMESITE': None,
 'SESSION_COOKIE_SECURE': False,
 'SESSION_REFRESH_EACH_REQUEST': True,
 'TEMPLATES_AUTO_RELOAD': None,
 'TESTING': False,
 'TRAP_BAD_REQUEST_ERRORS': None,
 'TRAP_HTTP_EXCEPTIONS': False,
 'USE_X_SENDFILE': False}

These are the default built-in configuration variables, which we can modify and change.

To modify any of these variables, we can just assign a new value to the key:

app.config["KEY"] = "value

For example, let’s update the configuration SECRET_KEY variable with the following:

app.config["SECRET_KEY"] = "iuhto743yto34iuho287gh78" print(app.config["SECRET_KEY"])

You’ll see the following in your terminal:

iuhto743yto34iuho287gh78

The SECRET_KEY value will now be permanently modified with the new value.

This method of updating config values works well for small applications which don’t require many configuration variables.

However it’s not very practical when you need to work across multiple environments and set several unique config values which you’ll need to access all across your app. Thankfully there’s a better way.

App Configuration file

Flask allows us to create a configuration file, where we can place all of our config values, overwrite the default values and alse create our own.

There are a few option for this, however we’re just going to cover our preferred method of creating a Python file and creating a Config class.

Go ahead and create a new file called config.py and place it in the same directory as your application entry point (Where you call app.run())

Here’s the barebones of the config.py file:

config.py

class Config(object):
    DEBUG = False
    TESTING = False

class ProductionConfig(Config):
    pass

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    TESTING = True

We first create the Config class and set some default attributes. In this case, we’ve set DEBUG and TESTING to False.

We then create 3 more classes, each of which inherits the Config class and attributes.

  • ProductionConfig - Is the config class we’ll use for running in production
  • DevelopmentConfig - Is the config class we’ll use for development
  • TestingConfig - Is the class we’ll use for testing

By the nature of class inheritance, all of our 3 subclasses have access to the Config class attributes and can be overwritten in any of the subclasses.

Let’s populate our config file with some attributes:

class Config(object):
    DEBUG = False
    TESTING = False
    SECRET_KEY = "B\xb2?.\xdf\x9f\xa7m\xf8\x8a%,\xf7\xc4\xfa\x91"

    DB_NAME = "production-db"
    DB_USERNAME = "admin"
    DB_PASSWORD = "example"

    IMAGE_UPLOADS = "/home/username/app/app/static/images/uploads"

    SESSION_COOKIE_SECURE = True

class ProductionConfig(Config):
    pass

class DevelopmentConfig(Config):
    DEBUG = True

    DB_NAME = "development-db"
    DB_USERNAME = "admin"
    DB_PASSWORD = "example"

    IMAGE_UPLOADS = "/home/username/projects/my_app/app/static/images/uploads"

    SESSION_COOKIE_SECURE = False

class TestingConfig(Config):
    TESTING = True

    DB_NAME = "development-db"
    DB_USERNAME = "admin"
    DB_PASSWORD = "example"

    SESSION_COOKIE_SECURE = False

We’ve assigned new values to some of the built-in config variables and created some of our own.

Production level attributes have been placed in the parent Config class which will be inherited by the ProductionConfig class, hence the pass.

Now that we’ve created our config file, we’ll need to instruct Flask to load it.

Loading a config file

Loading a config file is a simple one liner and should be placed as close to wherever you’ve created your app object.

It’s best practice to load the config as soon as possible, just after your app object is created so any other extension has access to your configuration variables.

We load a config file with the from_object() method, for example:

app.config.from_object("config_filename.ConfigClass")

For example, if we want to load the DevelopmentConfig class, we would do the following:

app.config.from_object("config.DevelopmentConfig")

For ProductionConfig:

app.config.from_object("config.ProductionConfig") 

In our case, we’ve placed this line in our __init__.py file, just underneath creating our app object:

app = Flask(__name__)
app.config.from_object("config.DevelopmentConfig")

The config has now been registered on the app and is now accessible from any part of your application.

For example, you may want to connect to a local database using the DevelopmentConfig settings in a different part or file in your app:

connect(
    name=app.config["DB_NAME"],
    username=app.config["DB_USERNAME"],
    password=app.config["DB_PASSWORD"]
)

Flask ENV

The ENV built-in configuration variable is extremely important and should always be set outside of your application, which we set with FLASK_ENV from the terminal.

If you’ve been following this series, you’ll know that we set this as an environment variable in the terminal before running the flask run command.

By default, ENV is set to production which disables DEBUG mode and avoids displaying the interactive debugger to the world, meaning if you just ran your application without explicitly setting FLASK_ENV, it would run in production mode.

Setting FLASK_ENV=development enables the debugger, which should never, ever be done in production!

I’ve found a nice pattern is to load a config based on the ENV environment variable. We can do so with the following:

app = Flask(__name__)

if app.config["ENV"] == "production":
    app.config.from_object("config.ProductionConfig")
else:
    app.config.from_object("config.DevelopmentConfig")

This pattern allows us to leave our code alone and control the config environment outside the application by setting the FLASK_ENV environment variable in the terminal.

To illustrate this, we’ll change our FLASK_ENV and print it after loading the config:

if app.config["ENV"] == "production":
    app.config.from_object("config.ProductionConfig")
else:
    app.config.from_object("config.DevelopmentConfig")

print(f'ENV is set to: {app.config["ENV"]}')

In the terminal, run the following to set FLASK_ENV to development

export FLASK_ENV=development

Run flask run and watch your terminal, you’ll see:

$ flask run

 * Serving Flask app "run.py" (lazy loading)
 * Environment: development
 * Debug mode: on
ENV is set to: development

Now repeat the process, changing FLASK_ENV to production:

export FLASK_ENV=production

Run flask run again and you’ll see:

$ flask run
 * Serving Flask app "run.py"
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
ENV is set to: production

Flask gives us a big red warning when the environment is set to production, just to drill home the importance of not running the development server in a production environment.

Alternative config methods

Flask is a very flexible framework and provides many ways to configure our application.

Take a look at the Flask configuration documentation for some alternative options and feel free to experiment with some alternative methods!

Last modified · 28 Feb 2019

Written with StackEdit.