Handling configuration parameters in Flask

Video thumbnail

Once you've created your first application with Flask. You must know how to use configuration files to set up the database, mode, etc. Configuration files in Flask allow us to add global parameters to our project; enable testing mode, debug mode, place the app's secret key used, for example, for data encryption, among many other configurations you can add in Flask.

Flask provides us with some mechanisms through which we can manage our project's configuration parameters, such as environment, database, connections to third-party services, etc.

These configurations are made in configuration files in Flask, which allow us to add global parameters to our project; enable testing mode, debug mode, place the app's secret key used, for example, for data encryption, among many other configurations you can add in Flask.

What are configurations in Flask and what are they for?

Configurations in Flask allow defining global project parameters: activating debug mode, connecting to a database, managing secret keys, or defining the working environment. In short, they tell the application how to behave in each context.

Configuration in Flask is either a class/subclass or simply a dictionary and can be modified programmatically and at runtime from our Flask project; for example, look at the following lines of code where we are programmatically changing the debug mode to true, and we do it through a configuration startup or simply a dictionary, and this way we can use the config object in Flask programmatically.

Most common global parameters

Some of the most used settings are:

app = Flask(__name__)
app.config['DEBUG'] = True
app.debug = True

Correctly configuring a Flask application is one of those tasks that seem simple... until it's time to change environments or deploy to production. In this guide, I'll tell you, from my experience developing and teaching Flask, how to manage all configurations: from the most basic to the advanced ones with classes, environments, and dynamic settings.

Configuration based on environment variables

As we discussed in the previous article, we also have configurations that we can use as environment variables:

DEBUG = True
TESTING = True
SECRET_KEY = "secrect"

For example, to modify the environment from an environment variable:

export FLASK_ENV=development flask run

The DEBUG parameter activates developer mode, TESTING allows running automated tests, and SECRET_KEY is used to encrypt cookies and sessions.

In my courses, I usually explain that good configuration is equivalent to avoiding many errors in production. A forgotten DEBUG=True can leak sensitive information to the end-user.

How Flask internally handles the app.config object

Flask uses a special dictionary called app.config that stores the active configurations. This object can be modified at runtime and accepts both its own variables and those defined by extensions (like SQLAlchemy or Flask-Mail).

How Flask internally handles the app.config object

Flask uses a special dictionary called app.config that stores the active configurations. This object can be modified at runtime and accepts both its own variables and those defined by extensions (like SQLAlchemy or Flask-Mail).

Configuration Parameters Based on Classes or Objects

Video thumbnail

This is the most complete and organized approach and is therefore the recommended one we use in our course; since, as we will see, it offers us the possibility of using different configurations depending on the environment we are in, we can set up different configuration parameters based on classes, which is a very interesting mechanism we have for having all kinds of configurations, and for different development environments.

Simply create a file with any name and a .py extension and add a class; for example, a file named configuration.py; for example, in our Flask course, we use the following configuration.

This method is the most professional and the one I recommend in my courses. It allows organizing configurations by environment (development, testing, production) and maintaining a clear structure.

class BaseConfig:
   SECRET_KEY = "Key"
   DEBUG = True
   TESTING = False
class ProductionConfig(BaseConfig):
   DEBUG = False
class DevelopmentConfig(BaseConfig):
   DEBUG = True
   TESTING = True

This is one I use in the course and book about Flask:

class BaseConfig(object):
   USER_APP_NAME = 'FlaskMalcen'
   USER_ENABLE_EMAIL = True
   'Base configuracion'
   SECRET_KEY = 'Key'
   DEBUG = True
   TESTING = False
   SQLALCHEMY_DATABASE_URI="mysql+pymysql://root:root@localhost:3306/pyalmacen2"
   RECAPTCHA_PUBLIC_KEY='6LffHtEUAAAAAI_KcKj6Au3R-bwhqRhPGe-WhHq_'
   RECAPTCHA_PRIVATE_KEY='6LffHtEUAAAAAJdHhV9e8yLOSB12rm8WW8CMxN7X'
   BABEL_TRANSLATION_DIRECTORIES='/*/flask_app/translations'
   #WTF_CSRF_TIME_LIMIT = 10
class ProductionConfig(BaseConfig):
   'Produccion configuracion'
   DEBUG = False
class DevelopmentConfig(BaseConfig):
   'Desarrollo configuracion'
   DEBUG = True
   TESTING = True
   SECRET_KEY = 'Desarrollo key'
   #MAIL_SUPPRESS_SEND = False
   MAIL_SERVER = "smtp.mailtrap.io"
   MAIL_PORT = 2525
   MAIL_USERNAME="xxx"
   MAIL_PASSWORD="xxx"
   #MAIL_DEFAULT_SENDER=('andres de DL',"andres@gmail.com")
   MAIL_USE_TLS=True
   MAIL_USE_SSL=False
   USER_EMAIL_SENDER_EMAIL="andres@gmail.com"
   CACHE_TYPE = "simple"

Then, we load the class according to the environment:

main.py

from config import DevConfig 
***
app = Flask(__name__) 
app.config.from_object(DevConfig)
***

Configuration based on environment variables

Ideal for cloud or Docker environments. You can define the Flask environment like this:

$ export FLASK_ENV=development
$ flask run

Or even use .env with the python-dotenv extension.

Configuration based on classes and inheritance between environments

Class inheritance allows defining a base class with common parameters and extending it for each environment. With this, we can inherit to other classes which will be the different environments or modes we want our application to have, and this is what we use in the Flask course.

In my case, I tend to use this pattern:

class BaseConfig:
   SECRET_KEY = 'Key'
   SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:root@localhost:3306/pyalmacen2"
class DevelopmentConfig(BaseConfig):
   DEBUG = True
   TESTING = True
   MAIL_SERVER = "smtp.mailtrap.io"
class ProductionConfig(BaseConfig):
   DEBUG = False

This way I can switch between environments simply by:

main.py

from config import DevConfig 
***
app = Flask(__name__) 
app.config.from_object(DevConfig)
# app.config.from_object('configuration.ProductionConfig')
***

Practical tip: define your sensitive variables (username, password, API keys) in a .env file or in your deployment system, never in the code.

The interesting thing about this is that we can easily use common configurations which are those in our class called BaseConfig and we can inherit them to other classes which are what we use to indicate the different modes of our application, and this is what we use in the Flask course.

⚡ Dynamic Configuration and Runtime Adjustments

Sometimes, we need Flask to adapt dynamically to certain values. For example, configuring a file upload folder based on the current path:

import os
app.config['UPLOAD_FOLDER'] = os.path.realpath('.') + '/static/uploads'

When I tested this approach in real projects, it allowed me to keep consistent paths in different environments without duplicating configurations.

You can also modify any parameter in real time:

app.config['CACHE_TYPE'] = 'simple'

This is very useful for quick tests or temporary adjustments without restarting the server.

As you can see, this is the most complete version you can choose when developing your Flask configurations, as we can easily vary between one environment and another, activating or deactivating certain configurations automatically by just changing one line of code.

Best Practices and Common Errors when Configuring Flask

  • Do not leave DEBUG=True in production.
    It can expose sensitive server information.
  • Do not include secret keys in the repository.
    Use environment variables (os.environ) or .env files.
  • Separate environments.
    Define different configurations for development, testing, and production.
  • Use class inheritance.
    Avoid duplicating configurations and centralize common ones in a base class.
  • ⚙️ Centralize everything in config.py.
    Facilitates project maintenance and portability.

❓ Frequently Asked Questions about Configurations in Flask

What is the best way to handle multiple environments in Flask?
Use configuration classes (BaseConfig, DevelopmentConfig, etc.) and load them according to the context.

What is the difference between from_object and from_pyfile?
from_object loads a Python class or module; from_pyfile reads a specific .py file. The former is more flexible for large projects.

How to protect the SECRET_KEY?
Store it in an environment variable or use python-dotenv to load it from a .env file.

Can environment variables be used to configure Flask?
Yes, and it is the most recommended for production.

Conclusion

Configuring Flask correctly makes the difference between a fragile app and a solid, scalable application.
From simple configurations with app.config to complete architectures with classes and inheritance, Flask gives you all the flexibility you need.

In my experience, the class-based approach offers the most benefits: organization, security, and ease of maintenance.

I agree to receive announcements of interest about this Blog.

We are going to talk about the Flask configuration files to manage global configurations to our project and also to manage different configurations depending on the environment.

| 👤 Andrés Cruz

🇪🇸 En español