Skip to main content

Flask Configuration

When building Flask applications, proper configuration management is essential for creating maintainable, secure, and environment-adaptable web applications. This guide will walk you through the various ways to configure your Flask applications, from simple in-code settings to sophisticated environment-based configurations.

Introduction to Flask Configuration

Configuration in Flask refers to the various settings that determine how your application behaves. These settings might include database URIs, secret keys, debugging flags, and other application-specific parameters. Flask provides flexible ways to manage these settings across different environments (development, testing, production).

Why Configuration Matters

  • Security: Properly configured applications keep sensitive information (like API keys) out of your code
  • Environment adaptability: Your app can behave differently in development vs. production
  • Maintainability: Centralized configuration makes it easier to update settings
  • Testability: Proper configuration makes testing easier with separate test settings

Basic Configuration Methods

1. Direct Configuration

The simplest way to configure Flask is by setting configuration values directly on your app's config dictionary:

python
from flask import Flask

app = Flask(__name__)

# Configuration directly on the app
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['DATABASE_URI'] = 'sqlite:///app.db'

@app.route('/')
def hello():
return "Hello, Flask!"

if __name__ == '__main__':
app.run()

This approach works for simple applications but doesn't scale well for larger projects.

2. Using Configuration Files

For more complex applications, you can keep your configuration in separate Python files:

python
# config.py
DEBUG = True
SECRET_KEY = 'your-secret-key'
DATABASE_URI = 'sqlite:///app.db'

Then import and use it in your app:

python
from flask import Flask

app = Flask(__name__)
app.config.from_object('config')

@app.route('/')
def hello():
return f"Database: {app.config['DATABASE_URI']}"

if __name__ == '__main__':
app.run()

3. Class-Based Configuration

A more structured approach uses classes for different environments:

python
# config.py
class Config:
DEBUG = False
TESTING = False
SECRET_KEY = 'your-secret-key'
DATABASE_URI = 'sqlite:///production.db'

class DevelopmentConfig(Config):
DEBUG = True
DATABASE_URI = 'sqlite:///development.db'

class TestingConfig(Config):
TESTING = True
DATABASE_URI = 'sqlite:///testing.db'

class ProductionConfig(Config):
# Production-specific settings
DATABASE_URI = 'sqlite:///production.db'

Using the configuration in your app:

python
from flask import Flask
import config

app = Flask(__name__)

# Choose the right configuration based on environment
app.config.from_object(config.DevelopmentConfig)

@app.route('/')
def hello():
if app.config['DEBUG']:
return f"Running in DEBUG mode with database: {app.config['DATABASE_URI']}"
return "Production mode"

if __name__ == '__main__':
app.run()

Environment Variables and Security

Hardcoding sensitive information like secret keys and database credentials in your code is a security risk. Using environment variables is a safer approach:

python
# config.py
import os

class Config:
SECRET_KEY = os.environ.get('SECRET_KEY', 'fallback-key-for-development')
DATABASE_URI = os.environ.get('DATABASE_URI', 'sqlite:///app.db')
DEBUG = os.environ.get('FLASK_DEBUG', '0') == '1'

To set these environment variables:

On Linux/Mac:

bash
export SECRET_KEY="my-super-secret-key"
export DATABASE_URI="sqlite:///production.db"
export FLASK_DEBUG=0
python app.py

On Windows:

bash
set SECRET_KEY=my-super-secret-key
set DATABASE_URI=sqlite:///production.db
set FLASK_DEBUG=0
python app.py

Configuration Best Practices

1. Using the python-dotenv Package

For easier environment variable management, use the python-dotenv package:

bash
pip install python-dotenv

Create a .env file in your project root:

# .env file
SECRET_KEY=my-super-secret-key
DATABASE_URI=sqlite:///dev.db
FLASK_DEBUG=1

Then load these variables in your app:

python
from flask import Flask
from dotenv import load_dotenv
import os

# Load environment variables from .env file
load_dotenv()

app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['DATABASE_URI'] = os.environ.get('DATABASE_URI')
app.config['DEBUG'] = os.environ.get('FLASK_DEBUG') == '1'

@app.route('/')
def hello():
return f"Using database: {app.config['DATABASE_URI']}"

if __name__ == '__main__':
app.run()
caution

Never commit your .env file to version control! Add it to your .gitignore file.

2. Configuration from JSON Files

Flask also supports loading configuration from JSON files:

python
import json
from flask import Flask

app = Flask(__name__)
app.config.from_file('config.json', load=json.load)

@app.route('/')
def hello():
return f"App name: {app.config.get('APP_NAME', 'Flask App')}"

if __name__ == '__main__':
app.run()

With a config.json file:

json
{
"APP_NAME": "My Flask Application",
"SECRET_KEY": "json-config-secret-key",
"DEBUG": true
}

Accessing Configuration Values

Once configured, you can access configuration values from anywhere in your application:

python
from flask import Flask, current_app

app = Flask(__name__)
app.config['APP_NAME'] = 'Configuration Demo'

@app.route('/')
def hello():
# Access through app.config
return f"Welcome to {app.config['APP_NAME']}"

@app.route('/debug')
def debug_status():
# Access through current_app when outside app context
if current_app.config.get('DEBUG'):
return "Debugging is enabled."
return "Debugging is disabled."

if __name__ == '__main__':
app.run(debug=True)

Real-World Example: Complete Configuration System

Here's a more complete example showing a production-ready configuration system:

python
# app_structure/
# ├── app/
# │ ├── __init__.py
# │ └── routes.py
# ├── config.py
# ├── .env
# └── run.py

# config.py
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

class Config:
"""Base config class"""
APP_NAME = "Flask App"
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-please-change')
SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
"""Development configuration"""
DEBUG = True
SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URI') or \
'sqlite:///dev.db'

class TestingConfig(Config):
"""Testing configuration"""
TESTING = True
SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URI') or \
'sqlite:///test.db'

class ProductionConfig(Config):
"""Production configuration"""
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or \
'sqlite:///prod.db'

# Dictionary to easily select the environment
config_dict = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
python
# app/__init__.py
from flask import Flask
from config import config_dict
import os

def create_app(config_mode='default'):
"""Create and configure the Flask app"""
app = Flask(__name__)

# Get configuration from environment or use default
env_config = os.environ.get('FLASK_CONFIG', config_mode)
app.config.from_object(config_dict[env_config])

# Initialize extensions here
# db.init_app(app)
# migrate.init_app(app, db)

# Register blueprints
from app.routes import main_blueprint
app.register_blueprint(main_blueprint)

return app
python
# app/routes.py
from flask import Blueprint, current_app

main_blueprint = Blueprint('main', __name__)

@main_blueprint.route('/')
def index():
app_name = current_app.config.get('APP_NAME')
environment = 'Development' if current_app.debug else 'Production'
return f"Welcome to {app_name}! Running in {environment} mode."
python
# run.py
from app import create_app

app = create_app()

if __name__ == '__main__':
app.run()

And a sample .env file:

SECRET_KEY=my-super-secret-production-key
FLASK_CONFIG=development
DEV_DATABASE_URI=sqlite:///instance/dev.db
DATABASE_URI=sqlite:///instance/prod.db

Flask's Built-in Configuration Values

Flask has several built-in configuration values with specific meanings:

Configuration KeyDefaultDescription
DEBUGFalseEnables debug mode
TESTINGFalseEnables testing mode
SECRET_KEYNoneSecret key for session security
PERMANENT_SESSION_LIFETIMEtimedelta(days=31)Lifetime of a permanent session
JSON_AS_ASCIITrueSerialize objects to ASCII-encoded JSON
TEMPLATES_AUTO_RELOADNoneReload templates when they change

Summary

Proper configuration management is crucial for building robust Flask applications. In this guide, we've covered:

  1. Basic configuration using the app.config dictionary
  2. File-based configuration with Python modules
  3. Class-based configuration for different environments
  4. Using environment variables for sensitive information
  5. Best practices for secure configuration management
  6. Accessing configuration values throughout your app
  7. A complete real-world configuration system

By implementing these patterns, you can create Flask applications that are secure, easily configurable, and adaptable to different environments.

Exercises

  1. Create a simple Flask application with different configurations for development and production environments.
  2. Implement a configuration system that uses environment variables for sensitive information.
  3. Create a Flask app that displays different information based on its configuration settings.
  4. Build a configuration system that automatically selects the right configuration based on an environment variable.
  5. Implement configuration for a Flask application with database connections that change based on the environment.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)