Skip to main content

The Config Object

Flask manages application settings through the Config class, a specialized dictionary that provides multiple ways to load values from files, objects, and environment variables. While it behaves like a standard Python dict, it enforces specific conventions—most notably the "uppercase only" rule—to distinguish between configuration settings and internal script variables.

The Uppercase Convention

When you load configuration from a Python file or object, Flask only imports keys that are written in all capital letters. This allows you to define temporary variables or helper functions in your config files without them being added to the application's configuration dictionary.

# config.py
DEBUG = True
SECRET_KEY = "dev-key"
internal_helper = "this will be ignored"

Internally, methods like from_object and from_mapping iterate through the source and check key.isupper() before assignment:

# From flask/config.py
for key in dir(obj):
if key.isupper():
self[key] = getattr(obj, key)

Loading Configuration

Flask provides several methods to populate the Config object, allowing you to separate defaults from environment-specific overrides.

From Objects and Modules

The from_object method is commonly used to load default settings from a class or a module. You can pass either the object itself or an import string.

class DefaultConfig:
DEBUG = False
DATABASE_URI = "sqlite:///:memory:"

app.config.from_object(DefaultConfig)
# Or using an import string:
app.config.from_object("yourapplication.default_config")

From Python Files

If you want to keep configuration in a separate script outside your package (useful for deployment), use from_pyfile. This method executes the file and loads its uppercase variables.

# Load from a file relative to the app's root_path
app.config.from_pyfile("config.py", silent=True)

Internally, from_pyfile creates a temporary module, reads the file content, and uses exec to populate that module's dictionary before passing it to from_object.

From JSON and TOML Files

For non-Python configuration formats, from_file allows you to use any loader that returns a mapping.

import json
app.config.from_file("config.json", load=json.load)

import tomllib
app.config.from_file("config.toml", load=tomllib.load, text=False)

From Environment Variables

For 12-factor apps, Flask offers two ways to leverage environment variables. The from_envvar method is a shortcut for loading a configuration file whose path is stored in an environment variable:

# export YOURAPP_SETTINGS='/path/to/real/config.py'
app.config.from_envvar("YOURAPP_SETTINGS")

Alternatively, from_prefixed_env loads variables directly from the environment if they share a common prefix (defaulting to FLASK_). It automatically converts JSON-like strings (numbers, booleans, dicts) into Python types.

# export FLASK_DEBUG=true
# export FLASK_DATABASE__HOST=localhost
app.config.from_prefixed_env()

assert app.config["DEBUG"] is True
assert app.config["DATABASE"]["HOST"] == "localhost"

The from_prefixed_env method handles nested dictionaries by looking for double underscores (__) in the environment variable name.

Organizing Configuration

A common pattern in Flask applications is to set defaults using a mapping and then override them with an external file or test configuration.

# From examples/tutorial/flaskr/__init__.py
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
)

if test_config is None:
# Load the instance config, if it exists, when not testing
app.config.from_pyfile("config.py", silent=True)
else:
# Load the test config if passed in
app.config.update(test_config)

Extracting Subsets

If you need to pass a group of settings to an external library (like a database driver or Celery), get_namespace can extract keys sharing a prefix and optionally strip that prefix.

app.config["DATABASE_HOST"] = "localhost"
app.config["DATABASE_USER"] = "admin"

# Extract database settings
db_config = app.config.get_namespace("DATABASE_")
# Result: {"host": "localhost", "user": "admin"}

Internal Integration: ConfigAttribute

Flask uses the ConfigAttribute descriptor to link certain attributes on the Flask application object directly to keys in the Config dictionary. This is why setting app.secret_key is equivalent to setting app.config["SECRET_KEY"].

In flask/sansio/app.py, these attributes are defined as:

secret_key = ConfigAttribute[str | bytes | None]("SECRET_KEY")
testing = ConfigAttribute[bool]("TESTING")

When you access app.secret_key, the ConfigAttribute.__get__ method retrieves the value from obj.config["SECRET_KEY"]. When you assign a value, __set__ updates the config dictionary accordingly.