Managing Django settings - keeping one's sanity

Presenter Notes

About me

Presenter Notes

State of the world

Pypi search: at least 40 packages about "Django settings"

  • Reading from various sources
  • Splitting settings across Python files
  • Storing settings in a database
  • Managing settings from the admin console
  • Configuring pluggable apps

Presenter Notes

Dissecting settings (1/3)

INSTALLED_APPS, AUTH_USER_MODEL, ...

  • "Linking"
  • Specific value required for the project to start
  • Almost stable between dev, test, staging, prod

Presenter Notes

Dissecting settings (2/3)

FOOBAR_EXPIRE_DELAY, MAX_ACCOUNTS, ...

  • similar to config.h
  • Define the application's behavior
  • Identical on dev, test, staging, prod
  • Related to business logic, changes may be required outside the usual release cycle

Presenter Notes

Dissecting settings (3/3)

DATABASES['HOST'], ALLOWED_HOSTS, SECRET_KEY

  • Runtime configuration
  • Depend on the production environment
  • ops-defined values

Presenter Notes

Loading settings: as Python code

# Import
try:
    from . import local_settings
except ImportError:
    pass

# Exec
execfile(
    '/etc/myproject/settings.py',
    globals(),
)

Presenter Notes

Loading settings: as Python code

Pros:

  • Just write Python
  • Same semantics everywhere

Cons:

  • Hard to understand where a value comes from
  • Hard to override complex setting layout: DATABASES['default']['HOST'] = '...'
  • Where should we deploy production settings?

Presenter Notes

What about deployment?

Presenter Notes

Development setup

  • Checkout based
  • Everything runs locally
  • Enable debug features
  • Disable remote APIs (Maps, ...)

Presenter Notes

Testing setup

  • Checkout based
  • Backends run locally (databases, caches, ...)
  • Some remote APIs may be connected with dedicated accounts
  • Enable coverage and verbose stacks

Presenter Notes

Staging, production

  • One installation per host
  • Backends run on distant servers
  • Service accounts
  • Defined by ops

Presenter Notes

A (possible) solution

Presenter Notes

A possible solution

  • A single settings.py file
  • One global setting, ENVIRONMENT (dev/prod), from the environment
  • Defines defaults for most environment-dependant values
  • Read the other values from environment and/or flat files

Presenter Notes

Example

# settings.py
import getconf
CONFIG = getconf.ConfigGetter('MYPROJ', [
    '/etc/myproj/settings/',
    os.path.join(ROOT_DIR, 'local_settings.ini'),
])

ENVIRONMENT = CONFIG.get('ENVIRONMENT', 'dev')

STATIC_URL = CONFIG.get('django.static_url', '/static/')
DATABASES = {'default': {
    'HOST': CONFIG.get('db.host', 'localhost'),
    'PORT': CONFIG.getint('db.port', '5432'),
    # ...
}}

Presenter Notes

Example

Configure through INI files:

# /etc/myproj/settings/base.ini
[DEFAULT]
environment = prod

[django]
static_url = https://static.example.org/

[db]
host = psql01.example.org

# /etc/myproj/settings/passwords.ini
[db]
password = !!TopSicrit!!

Presenter Notes

Example

Or environment variables:

export MYPROJ_DJANGO_STATIC_URL=https://static.example.org/
export MYPROJ_DB_HOST=psql01.example.org

Presenter Notes

getconf

  • Reads values from both environment and configuration files
    • Environment for continuous integration and Heroku-like platforms
    • Flat files for local development and traditional hosting
  • Handles namespacing through INI files sections
  • Uses a prefix for environment variables to avoid name conflicts
  • Provides some simple parsing features (int, bool, float, list)

Designed to solve a single problem:

Get environment-dependent settings in the platform-typical way.

Presenter Notes

Pluggable apps

  • May need all kinds of settings (linking, app config, platform)
  • Just read from django.conf.settings
  • Define defaults with django-appconf <http://django-appconf.readthedocs.org/en/latest/>
# myapp/conf.py
import appconf
from django.conf import settings

class MyAppConf(appconf.AppConf):
    MYAPP_MAX_QUERIES = 5
    MYAPP_USER_MODEL = settings.AUTH_USER_MODEL

Presenter Notes

Links

Also, we're hiring!

Presenter Notes