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 productionDevelopmentConfig
- Is the config class we’ll use for developmentTestingConfig
- 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.