Skip to main content

Configuring Application State

To manage application settings in this project, you use the config attribute of the App class. This object is a specialized dictionary that allows you to load configuration from Python objects, files, and environment variables.

Initializing Configuration in an Application Factory

The recommended way to configure your application is within an application factory. This allows you to set defaults and then override them with instance-specific files or environment variables.

import os
from flask import Flask

def create_app(test_config=None):
# instance_relative_config=True makes paths relative to the instance folder
app = Flask(__name__, instance_relative_config=True)

# 1. Set default configuration
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
)

if test_config is None:
# 2. Load the instance config, if it exists, when not testing
# This file is looked up in the instance folder
app.config.from_pyfile("config.py", silent=True)
else:
# 3. Load the test config if passed in
app.config.from_mapping(test_config)

return app

Loading from Environment Variables

You can load configuration directly from environment variables using from_prefixed_env. By default, it looks for variables starting with FLASK_.

# If environment has:
# FLASK_SECRET_KEY="production-key"
# FLASK_DATABASE__HOST="localhost"

app.config.from_prefixed_env()

# Resulting config:
# app.config["SECRET_KEY"] == "production-key"
# app.config["DATABASE"] == {"HOST": "localhost"}

Key features of from_prefixed_env:

  • Prefix: Defaults to FLASK_. You can change this via app.config.from_prefixed_env(prefix="MYAPP").
  • Type Conversion: It uses json.loads by default. Values like true, 1, or {"a": 1} are converted to their Python equivalents.
  • Nested Keys: Use double underscores (__) to create nested dictionaries in the configuration.

Loading from Files (JSON/TOML)

The from_file method allows you to load configuration from various formats by providing a loader function.

import json
import tomllib

# Load from a JSON file
app.config.from_file("config.json", load=json.load)

# Load from a TOML file (requires binary mode)
app.config.from_file("config.toml", load=tomllib.load, text=False)

Using Class-Based Configuration

For complex applications, you might want to organize settings into classes. Use from_object to load uppercase attributes from a class or module.

class Config:
DEBUG = False
TESTING = False
DATABASE_URI = "sqlite:///:memory:"

class ProductionConfig(Config):
DATABASE_URI = "mysql://user@localhost/foo"

app.config.from_object(ProductionConfig)

Accessing Configuration

You can access configuration values using standard dictionary syntax or through convenience attributes on the App instance.

# Dictionary access
db_uri = app.config["DATABASE_URI"]

# Proxy attributes (ConfigAttribute)
# These map directly to app.config["DEBUG"], app.config["SECRET_KEY"], etc.
app.debug = True
app.secret_key = "super-secret"
print(app.testing)

The App class provides several ConfigAttribute proxies:

  • debug: Maps to DEBUG.
  • testing: Maps to TESTING.
  • secret_key: Maps to SECRET_KEY.
  • permanent_session_lifetime: Maps to PERMANENT_SESSION_LIFETIME.

Troubleshooting Configuration

Uppercase Requirement

The Config class only loads keys that are fully uppercase. Lowercase attributes in a Python file or keys in a mapping are ignored.

# This will be loaded
app.config.from_mapping(DEBUG=True)

# This will be ignored
app.config.from_mapping(debug=True)

Path Resolution

If instance_relative_config=True is set in the App constructor, relative paths passed to from_pyfile or from_file are resolved relative to the application's instance folder. Otherwise, they are relative to the application's root path.

Late Debug Setting

Setting app.debug after the application has started handling requests may not behave as expected, as some extensions and internal components (like the Jinja environment) check this value during initialization. Always perform configuration before calling app.run() or handling the first request.