My Flask Configuration Handling

I’ve built a few applications using Flask, but I’ve had trouble handling configuration, especially when it comes to handling different environments.

But I’ve found a way that works, is simple, and is easy even when using multiple environments. I’ll share the details below, or you can go view it on Gist.

The Problem

As mentioned, the main issue I’d had was with switching between different environments (production, development, testing). For instance, in each environment, I’d need to specify the URL of a different database to use.

In previous applications, I would handle this issue by using different configuration files for each environment, and switch the file depending on the environment I was working with.

I didn’t like this approach for 2 reasons:

  1. It was open to user error (what if I forgot to switch settings files and launched to production)
  2. It seemed like more work than was necessary (overly complex)

So I went seeking for a solution.

The Flask documentation presents a few ways to handle configuration, but I wasn’t thrilled with their options. They either required too much input from a user (open to human error) or were a bit too complex (I wanted to make this as simple as possible).

But I did see a line in the documentation which stated: “Use an environment variable to switch between the configurations.”

Going with this idea and combining it with some of the example configurations, I came up with an elegant solution.

The Solution

The basic idea is to set all configurations within one configuration file. Then the user can set an environment variable which Flask can use to tell which environment it is in. Switching environments just requires changing that environment variable.

I liked this approach because it required only one action of the user (setting an environment variable) and abstracted the complexity away (no more need for multiple configuration files). I also can easily use the same code in each environment (no more multiple repos).

Here is the code I ended up with:


import os
# Get environment, or set to development by default
app_env = os.environ.get('APPLICATION_ENVIRONMENT') or 'development'
# Settings applied to all environments
SECRET_KEY = 'development key'
# Settings applied to specific environments
if app_env == 'production':
DATABASE_URI = '' # TODO: Enter your production database
DEBUG = False
elif app_env == 'development':
DATABASE_URI = '' # TODO: Enter your dev database
DEBUG = True
elif app_env == 'testing':
DATABASE_URI = '' # TODO: Enter your test database

So what’s going on here?

We are first reading the environment variable APPLICATION_ENVIRONMENT. If there is none set, it defaults to 'development'.

We can then set the configuration settings which are applicable to all environments (such as the SECRET_KEY).

Then, we can override settings depending on the current environment, such as setting a different database for each environment.

How I Used This In My Workflow

I’ve been working on a bookmarking/link shortening application (https://github.com/byanofsky/bookmarks/) which I deployed to Heroku.

On the Heroku production server, I set the APPLICATION_ENVIRONMENT to 'production'.

On my local Vagrant server where I do development and testing, I easily switch between the two environments as needed.

I also created a fourth environment that I use for staging that connects with a staging server on Heroku and test with Heroku Local.

Switching between environments is easy, which makes managing my code simpler.

Last Thoughts

Hopefully this helps you with your Flask configuration handling.

If you find ways I can improve this, please let me know in the comments.

Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s