Settings in Django application

23
Settings in Django Applications Handling of settings in various environments Tomáš Sirný @junckritter

Transcript of Settings in Django application

Page 1: Settings in Django application

Settings in Django

ApplicationsHandling of settings in various environments

Tomáš Sirný

@junckritter

Page 2: Settings in Django application

Default

• 1 file - settings.py

• good for local development

• deploy to production?

• different environments / developer machines

(OSX/Win)

• to git or not to git?

Page 3: Settings in Django application

Simple solution

• if-clause for name of production/devel machine

• magic with imports from different files

• manually curated file on production machine

• …

Page 4: Settings in Django application

Problems

• Hard to manage different sets of settings

• Copying of files/code snippets in deploy scripts,

test/build configs

• Not replicable if not versioned

• No recommendation in Django documentation

Page 5: Settings in Django application

The right way

• based on https://speakerdeck.com/jacobian/the-

best-and-worst-of-django?slide=81 (by Django’s

contributor)

• Two Scoops of Django

Page 6: Settings in Django application
Page 7: Settings in Django application

Principles

• common parts to base.py

• separate file for each environment

• use env variable DJANGO_SETTINGS_MODULEor CLI parameter --settings= for ./manage.py

• everything is in git

• easy additions/changes of particular setting values

Page 8: Settings in Django application

Our setup• __init__.py

• base.py

• helpers.py

• local.tpl.py

• admin.py

• staging.py

• production.py

Page 9: Settings in Django application

base.py

• sane defaults - application could (mostly) run as-is

• INSTALLED_APPS, DEBUG, DATABASES,

CACHES

• settings for applications

Page 10: Settings in Django application

helpers.py

• code running at the end

• generate final settings based on temporary ones

DEBUG_MODULES = ['action', ‘emails’] in local.py

for module in globals().get('DEBUG_MODULES', []):

LOGGING[‘loggers’][module] = …

Page 11: Settings in Django application

local.tpl.py

• template for local development

• good starting point for newcomer

• good place to manifest changes / new settings,

visible in VCS diff

Page 12: Settings in Django application

[environment].py

• from .base import *

• …

• execfile(os.path.join(PROJECT_PATH,

'project/settings/helpers.py

Page 13: Settings in Django application

[environment].py

• only changes for particular environment

• diff against base.py (or Django’s global settings)

• $DJANGO_SETTINGS_MODULE=[environment].py

Page 14: Settings in Django application

Pros

• More control

• Easy check/reference to particular setting

• Easier build/deployment

• Documented changes/defaults

Page 15: Settings in Django application

Cons

• Possible duplication for similar environments

(admin, production) - more layers, shared parts

• env variable have to be set everywhere

Page 16: Settings in Django application

Tips & tricks

Page 17: Settings in Django application

Settings for applications

• settings file is big chunk of code

• all settings in one (or few) place(s)

• harder to find settings for particular application

Page 18: Settings in Django application

Our solution

• settings.py in each application with defaults

• app1/settings.py

• app2/settings.py

• global settings file can override

• APP_SETTING =

settings.get(‘GLOBAL_APP_SETTING, ‘default’)

Page 19: Settings in Django application

Cache invalidation

• hard problem in CS

• especially during deployment/migration

• format of key is usually tied to version of code

Page 20: Settings in Django application

Cache invalidation

in base.py

from subprocess import check_output, CalledProcessError

try:

VERSION = check_output(

'git rev-parse --short=8 HEAD',

shell=True

).strip()

except CalledProcessError:

VERSION = 'test'

Page 21: Settings in Django application

Cache invalidation

in production.py

CACHES = {

'default': {

'BACKEND': 'project.cache.EnhancedRedisCache',

'LOCATION': 'redis:6379',

'VERSION': VERSION,

'OPTIONS': {

'DB': 1,

'PASSWORD': '',

'PARSER_CLASS': 'redis.connection.HiredisParser'

}

}

}

Page 22: Settings in Django application

One more thing

Page 23: Settings in Django application

Migrate Postgres

psql -h <host1> ... -c 'copy (select ... from

<tablename> where …) to stdout' |

psql -h <host2> ... -c 'copy <tablename> from stdin'