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 feedback@compilenrun.com. I’d greatly appreciate your feedback! :)