Configuration
Every Flask app needs settings — database URLs, secret keys, debug modes. Hardcoding these in your app is a bad idea because different environments need different values. Flask's configuration system lets you manage settings cleanly across development, testing, and production.
The config Dictionary
Flask stores configuration in app.config, which behaves like a dictionary. You can set values directly or load them from an object.
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///dev.db'
app.config['DEBUG'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
The SECRET_KEY is critical — it's used for signing sessions, cookies, and other security features. Never commit this to version control.
Config Classes
For real apps, organize your settings into classes. Each environment gets its own class with appropriate values.
import os
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-fallback-key')
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///dev.db'
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///test.db'
class ProductionConfig(Config):
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
app = Flask(__name__)
app.config.from_object(config[os.environ.get('FLASK_ENV', 'default')])
Now you just set the FLASK_ENV environment variable and the right configuration loads automatically. Development uses SQLite, testing uses a separate test database, and production pulls from environment variables.
Environment Variables
Environment variables are the standard way to handle secrets and environment-specific values. They live outside your code so they never get committed to git.
# Reading environment variables
import os
secret_key = os.environ.get('SECRET_KEY')
database_url = os.environ.get('DATABASE_URL')
debug_mode = os.environ.get('DEBUG', 'False').lower() == 'true'
# Set defaults for development
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret')
app.config['DEBUG'] = os.environ.get('DEBUG', 'True').lower() == 'true'
.env Files with python-dotenv
During development, manually setting environment variables is tedious. The python-dotenv library lets you put them in a .env file that loads automatically.
# Install: pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # Loads variables from .env file
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL')
Your .env file would look like this:
SECRET_KEY=my-super-secret-key
DATABASE_URL=sqlite:///dev.db
DEBUG=True
Make sure .env is in your .gitignore — it contains secrets that should never be in version control.
Key Configuration Values
Every Flask app needs a few essential settings. SECRET_KEY for security, SQLALCHEMY_DATABASE_URI for the database, and DEBUG for development mode. Beyond that, you'll add things like mail server settings, API keys, and file upload limits as your app grows.
Why Configuration Management Matters
Good configuration management means your app works everywhere without code changes. Developers run with debug mode on, testers use a test database, and production uses secure environment variables. It's the difference between an app that "works on my machine" and one that works everywhere.