Settings

This file outlines the settings and setting files used in this project.

The settings files are all located inside the settings package at the top level of the project.

This package contains two settings files by default, base.py and local.py.example.

base.py

This is the base settings file for the project. It contains all of the default settings across all the different environments.

It is split into logical sections:

Directory setup

A lot of settings in Django require full paths instead of relative paths. We can use some tricks inside the settings file to enable us to determine the location of the project and then use relative paths from there.

PROJECT_DIR

PROJECT_DIR is the absolute path to the package for the project.

PROJECT_DIR = os.path.dirname(os.path.realpath(project_module.__file__))
PROJECT_ROOT

PROJECT_ROOT is the absolute path to the root directory of the project.

PROJECT_ROOT = os.path.dirname(PROJECT_DIR)
VAR_ROOT

VAR_ROOT is the absolute path to the var/ directory inside the root directory of the project.

VAR_ROOT = os.path.join(PROJECT_ROOT, 'var')
BIN_ROOT

BIN_ROOT is the absolute path to the bin/ directory inside the root directory of the project.

BIN_ROOT = os.path.join(PROJECT_ROOT, 'bin')

Generic Django project settings

SITE_ID

SITE_ID is a unique ID for each Django site. It’s used as part of the django.contrib.sites application.

SITE_ID = 1
See also, Django’s documentation for SITE_ID
https://docs.djangoproject.com/en/1.4/ref/settings/#site-id

Admin/managers

ADMINS

ADMINS is the list of administrators for the site. You should change this to be your name and email address. These are the people who will see the error traceback emails.

ADMINS = (
    ('You', 'your@email'),
)
See also, Django’s documentation for ADMINS
https://docs.djangoproject.com/en/1.4/ref/settings/#admins
MANAGERS

MANAGERS is the list of managers for the site. By default Django only uses this emails to send 404 error emails. However the sending of 404 error emails if off by default. By default this is just set to the same as ADMINS.

MANAGERS = ADMINS
See also, Django’s documentation for MANAGERS
https://docs.djangoproject.com/en/1.4/ref/settings/#managers

Localization settings

TIME_ZONE

TIME_ZONE specifies the default timezone for the installation.

TIME_ZONE = 'America/Los_Angeles'
See also, Django’s documentation for TIME_ZONE
https://docs.djangoproject.com/en/1.4/ref/settings/#time-zone
USE_TZ

Setting USE_TZ to True enables timezone support and use timezone aware datetimes. Timezones help give context to datetimes and it makes sense to always use them to reduce ambiguity.

USE_TZ = True
See also, Django’s documentation for USE_TZ
https://docs.djangoproject.com/en/1.4/ref/settings/#use-tz
USE_I18N

Setting USE_I18N to True enables Django’s internationalization support.

USE_I18N = True
See also, Django’s documentation for USE_I18N
https://docs.djangoproject.com/en/1.4/ref/settings/#use-i18n
USE_L10N

Setting USE_L10N to True enables Django’s localization support.

USE_L10N = True
See also, Django’s documentation for USE_L10N
https://docs.djangoproject.com/en/1.4/ref/settings/#use-l10n
LANGUAGE_CODE

LANGUAGE_CODE controls the default language for the site. We set it to English by default.

LANGUAGE_CODE = 'en'
See also, Django’s documentation for LANGUAGE_CODE
https://docs.djangoproject.com/en/1.4/ref/settings/#language-code
LANGUAGES

LANGUAGES is a list of all the languages that this site supports. By default since many of our sites don’t use anything other than English, it is just set to English.

If your site supports other languages you can add them here.

Note

Django supports many languages out of the box, and all of Django’s UI is translated into those languages. However since the rest of your site isn’t translated, it tends to be a better user experience to just list the languages that your entire site supports.

LANGUAGES = (
    ('en', 'English'),
)
See also, Django’s documentation for LANGUAGES
https://docs.djangoproject.com/en/1.4/ref/settings/#languages
Django’s supported languages
https://github.com/django/django/blob/stable/1.4.x/django/conf/global_settings.py#L47

Installed apps

INSTALLED_APPS

INSTALLED_APPS is the list of installed Django applications for the site. This list is separated into sections to make it clear where the app is from.

INSTALLED_APPS = (
    # Local Apps
    # '{{ project_name }}.apps.',

    # Third Party Apps
    'south',
    'compressor',
    'waffle',
    'django_nose',
    'djangosecure',
    'djcelery',

    # Django Apps
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'django.contrib.admindocs',
)
See also, Django’s documentation for INSTALLED_APPS
https://docs.djangoproject.com/en/1.4/ref/settings/#installed-apps

Project URLS and media settings

ROOT_URLCONF

ROOT_URLCONF is the python path to the root URL module to use for the project.

ROOT_URLCONF = '{{ project_name }}.urls'
See also, Django’s documentation for ROOT_URLCONF
https://docs.djangoproject.com/en/1.4/ref/settings/#root-urlconf
LOGIN_URL

LOGIN_URL is the URL which points to the login view. This setting is used primarily to redirect to the login page when a view comes across a permissions error.

LOGIN_URL = '/login/'
See also, Django’s documentation for LOGIN_URL
https://docs.djangoproject.com/en/1.4/ref/settings/#login-url
LOGOUT_URL

LOGOUT_URL is the URL which points to the logout view.

LOGOUT_URL = '/logout/'
See also, Django’s documentation for LOGOUT_URL
https://docs.djangoproject.com/en/1.4/ref/settings/#logout-url
LOGIN_REDIRECT_URL

LOGIN_REDIRECT_URL points the URL that the user should be redirected to after a successful login where no next parameter is provided to the login view.

LOGIN_REDIRECT_URL = '/'
See also, Django’s documentation for LOGIN_REDIRECT_URL
https://docs.djangoproject.com/en/1.4/ref/settings/#login-redirect-url
STATIC_URL

STATIC_URL is the URL where static files are served from.

Note

By default we use the relative URL /static/, but this setting can take a complete URL such as http://static.example.com/. This is handy when you are using a CDN or other file hosting provider.

STATIC_URL = '/static/'
See also, Django’s documentation for STATIC_URL
https://docs.djangoproject.com/en/1.4/ref/settings/#static-url
MEDIA_URL

MEDIA_URL is the URL where uploaded media will be served from.

Note

By default we use the relative URL /uploads/, but this setting can take a complete URL such as http://uploads.example.com/. This is handy when you are using a CDN or other file hosting provider.

MEDIA_URL = '/uploads/'
See also, Django’s documentation for MEDIA_URL
https://docs.djangoproject.com/en/1.4/ref/settings/#media-url
STATIC_ROOT

STATIC_ROOT is the absolute path to where the django.contrib.staticfiles app will place the files it finds when running the collectstatic management command.

By default it’s var/static/.

STATIC_ROOT = os.path.join(VAR_ROOT, 'static')
See also, Django’s documentation for STATIC_ROOT
https://docs.djangoproject.com/en/1.4/ref/settings/#static-root
MEDIA_ROOT

MEDIA_ROOT is the absolute path to where Django will store uploaded files when using the default file storage system.

By default it’s var/uploads/.

MEDIA_ROOT = os.path.join(VAR_ROOT, 'uploads')
See also, Django’s documentation for MEDIA_ROOT
https://docs.djangoproject.com/en/1.4/ref/settings/#media-root
STATICFILES_DIRS

STATICFILES_DIRS lists the directories that the django.contrib.staticfiles app will look for files.

By default it’s {{ project_name }}/static/.

STATICFILES_DIRS = (
    os.path.join(PROJECT_DIR, 'static'),
)
See also, Django’s documentation for STATICFILES_DIRS
https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_FINDERS

STATICFILES_FINDERS is a list of classes that find static files for the django.contrib.staticfiles app. We are adding the Django Compressor finder to the list.

STATICFILES_FINDERS += (
    'compressor.finders.CompressorFinder',
)
See also, Django’s documentation for STATICFILES_FINDERS
https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#std:setting-STATICFILES_FINDERS

Templates

Settings that control where Django finds templates and how they are rendered.

TEMPLATE_DIRS

TEMPLATE_DIRS is a list of directories that Django will look in for templates.

By default it will only look in {{ project_name }}/templates/.

TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, 'templates'),
)
See also, Django’s documentation for TEMPLATE_DIRS
https://docs.djangoproject.com/en/1.4/ref/settings/#template-dirs
TEMPLATE_CONTEXT_PROCESSORS

TEMPLATE_CONTEXT_PROCESSORS is a list of functions that modify every template context that is rendered with RequestContext.

TEMPLATE_CONTEXT_PROCESSORS += (
    'django.core.context_processors.request',
)
See also, Django’s documentation for TEMPLATE_CONTEXT_PROCESSORS
https://docs.djangoproject.com/en/1.4/ref/settings/#template-context-processors
Django’s documentation for django.core.context_processors.request()
https://docs.djangoproject.com/en/1.4/ref/templates/api/#django-core-context-processors-request

Middleware

MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES is a list of classes that act on each request and response.

By default we use ten pieces of middleware.

{{ project_name }}.utils.middleware.request_id.RequestIdMiddleware

Adds a unique request.id attribute to each request.

This middleware is useful when trying to trace a request through the logs.

If you are using the {{ project_name }}.utils.logging.formatters.JSONFormatter for logging and you include a request object in your extra dictionary passed to logging calls, this ID will be displayed in the final JSON output.

django.middleware.common.CommonMiddleware

Performs URL rewriting based on the APPEND_SLASH and PREPEND_WWW settings.

If APPEND_SLASH is True and the initial URL doesn’t end with a slash, and it is not found in the URLconf, then a new URL is formed by appending a slash at the end. If this new URL is found in the URLconf, then Django redirects the request to this new URL. Otherwise, the initial URL is processed as usual.

For example, foo.com/bar will be redirected to foo.com/bar/ if you don’t have a valid URL pattern for foo.com/bar but do have a valid pattern for foo.com/bar/.

See also, Django’s documentation for django.middleware.common.CommonMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.middleware.common.CommonMiddleware
django.contrib.sessions.middleware.SessionMiddleware

Enables Django’s sessions application. Handles the creation of the session cookie and session storage.

See also, Django’s documentation for django.contrib.sessions.middleware.SessionMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.contrib.sessions.middleware.SessionMiddleware
django.middleware.transaction.TransactionMiddleware

Handles database transactions based on the Django request/response cycle.

It starts a new transaction at the begging of a request and commits the transaction once the request has been completed successfully. If the request fails for any reason it performs a rollback on the transaction.

See also, Django’s documentation for django.middleware.transaction.TransactionMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.middleware.transaction.TransactionMiddleware
django.middleware.csrf.CsrfViewMiddleware

Handles CSRF verifcation on POST requests.

See also, Django’s documentation for django.middleware.csrf.CsrfViewMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware
django.contrib.auth.middleware.AuthenticationMiddleware

Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object.

See also, Django’s documentation for django.contrib.auth.middleware.AuthenticationMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.contrib.auth.middleware.AuthenticationMiddleware
django.contrib.messages.middleware.MessageMiddleware

Enables cookie- and session-based message support.

See also, Django’s documentation for django.contrib.messages.middleware.MessageMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.contrib.messages.middleware.MessageMiddleware
djangosecure.middleware.SecurityMiddleware

Enables all the features of django-secure. Primarily it adds headers to the response for additional security.

See also, Django Secure’s documentation for djangosecure.middleware.SecurityMiddleware
https://django-secure.readthedocs.org/en/latest/middleware.html#securitymiddleware
django.middleware.clickjacking.XFrameOptionsMiddleware

Adds the X-Frame-Options header to each request. See the X_FRAME_OPTIONS setting.

See also, Django’s documentation for django.middleware.clickjacking.XFrameOptionsMiddleware
https://docs.djangoproject.com/en/1.4/ref/middleware/#django.middleware.clickjacking.XFrameOptionsMiddleware
class waffle.middleware.WaffleMiddleware

Enables all of the features of django_waffle. Primarily it handles the cookies that django_waffle uses.

MIDDLEWARE_CLASSES = (
    '{{ project_name }}.utils.middleware.request_id.RequestIdMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.transaction.TransactionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'djangosecure.middleware.SecurityMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'waffle.middleware.WaffleMiddleware',
)
See also, Django’s documentation for MIDDLEWARE_CLASSES
https://docs.djangoproject.com/en/1.4/ref/settings/#middleware-classes

Security settings

X_FRAME_OPTIONS

X_FRAME_OPTIONS controls the contents of the X-Frame-Options header that is set when using the django.middleware.clickjacking.XFrameOptionsMiddleware middleware.

This header controls whether or not a browser will show the page in an iframe. This can be used to prevent clickjacking.

It can either be SAMEORIGIN or DENY.

SAMEORIGIN allows for the page to put into a frame if it’s on the same site.

DENY never allows the page to be shown in a frame.

We set it to DENY for all pages as it is the most secure option.

If you need to override this for a specific, view Django provides decorators to turn it off for just that view. See Django’s documentation on clickjacking.

X_FRAME_OPTIONS = 'DENY'
See also, Django’s documentation for X_FRAME_OPTIONS
https://docs.djangoproject.com/en/1.4/ref/settings/#x-frame-options
INTERNAL_IPS

INTERNAL_IPS controls which IP addresses Django sees as being internal.

The Django Debug Toolbar app will only show the toolbar when the request originates from a IP address listed in INTERNAL_IPS.

INTERNAL_IPS = ('127.0.0.1',)
See also, Django’s documentation for INTERNAL_IPS
https://docs.djangoproject.com/en/1.4/ref/settings/#internal-ips

Setting SESSION_COOKIE_HTTPONLY to True sets the Django session cookie to use the HttpOnly flag on the cookie. This disables access to the cookie via Javascript. It reduces the risk of session hijacking because no Javascript on the page, malicious or otherwise, will have access to the session cookie.

SESSION_COOKIE_HTTPONLY = True
See also, Django’s documentation for SESSION_COOKIE_HTTPONLY

https://docs.djangoproject.com/en/1.4/ref/settings/#session-cookie-httponly

Learn more about the HttpOnly flag
https://en.wikipedia.org/wiki/HTTP_cookie#HttpOnly_cookie
SECURE_CONTENT_TYPE_NOSNIFF

Some browsers will try to guess the content types of the assets that they fetch, overriding the Content-Type header. While this can help display sites with improperly configured servers, it can also pose a security risk.

If your site serves user-uploaded files, a malicious user could upload a specially-crafted file that would be interpreted as HTML or Javascript by the browser when you expected it to be something harmless.

To learn more about this header and how the browser treats it, you can read about it on the IE Security Blog.

To prevent the browser from guessing the content type, and force it to always use the type provided in the Content-Type header, you can pass the X-Content-Type-Options: nosniff header.

Setting SECURE_CONTENT_TYPE_NOSNIFF to True adds this header to all requests.

SECURE_CONTENT_TYPE_NOSNIFF = True
See also, Django Secure’s Documentation for SECURE_CONTENT_TYPE_NOSNIFF
http://django-secure.readthedocs.org/en/latest/settings.html#secure-content-type-nosniff
SECURE_BROWSER_XSS_FILTER

Some browsers have to ability to block content that appears to be an XSS attack. They work by looking for Javascript content in the GET or POST parameters of a page. If the Javascript is replayed in the server’s response the page is blocked from rendering and a error page is shown instead.

The X-XSS-Protection header is used to control the operation of the XSS filter.

To enable the XSS filter in the browser, and force it to always block suspected XSS attacks, you can pass the X-XSS-Protection: 1; mode=block header.

Setting SECURE_BROWSER_XSS_FILTER to True will add this header to all requests.

Warning

The XSS filter does not prevent XSS attacks on your site, and you should ensure that you are taking all other possible mesaures to prevent XSS attacks. The most obvious of these is validating and sanitizing all input.

SECURE_BROWSER_XSS_FILTER = True
See also, Django Secure’s Documentation for SECURE_BROWSER_XSS_FILTER
http://django-secure.readthedocs.org/en/latest/settings.html#secure-browser-xss-filter
PASSWORD_HASHERS

PASSWORD_HASHERS is a list of classes that Django will use to hash passwords as part of it’s authentication system.

The top class of the list is the hasher that is used. The other hasher are listed so that Django can upgrade users with old hashes to default hasher.

We change the default password hasher to django.contrib.auth.hashers.BCryptPasswordHasher so that our passwords will be hashed using the bcrypt.

bcrypt is a hashing algorithm based on the blowfish encryption cipher. It is specifically designed to slow and hard to compute so that brute force attacks are less effective.

Warning

django.contrib.auth.hashers.BCryptPasswordHasher requires the py-bcrypt package to work. py-bcrypt is a C package and may not be available on all hosting platforms.

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)
See also, Django’s documentation for PASSWORD_HASHERS
https://docs.djangoproject.com/en/dev/topics/auth/#how-django-stores-passwords

Test settings

TEST_RUNNER

TEST_RUNNER controls which test runner Django will use when manage.py test is used.

We change it to use the django_nose.NoseTestSuiteRunner so that Django will use nose to find and run our tests.

TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
See also, Django’s documentation for TEST_RUNNER
https://docs.djangoproject.com/en/1.4/ref/settings/#test-runner

Email settings

DEFAULT_FROM_EMAIL

DEFAULT_FROM_EMAIL sets the default From: address on emails sent via Django.

You should change this to no-reply@DOMAIN_NAME.com where DOMAIN_NAME is your websites domain.

DEFAULT_FROM_EMAIL = 'no-reply@localhost'
See also, Django’s documentation for DEFAULT_FROM_EMAIL
https://docs.djangoproject.com/en/1.4/ref/settings/#default-from-email
SERVER_EMAIL

SERVER_EMAIL sets the From: email address that Django uses to send it’s error traceback emails. By default we just set it to the same as DEFAULT_FROM_EMAIL.

SERVER_EMAIL = DEFAULT_FROM_EMAIL
See also, Django’s documentation for SERVER_EMAIL
https://docs.djangoproject.com/en/1.4/ref/settings/#server-email
EMAIL_SUBJECT_PREFIX

EMAIL_SUBJECT_PREFIX is the string that Django will prefix the subject of the error traceback emails.

EMAIL_SUBJECT_PREFIX = '[Django - {{ project_name }}] '
See also, Django’s documentation for EMAIL_SUBJECT_PREFIX
https://docs.djangoproject.com/en/1.4/ref/settings/#email-subject-prefix

Django Compressor settings

COMPRESS_PARSER

COMPRESS_PARSER controls which HTML parser Django Compressor will use when parsing {% templatetag openblock %} compress {% templatetag closeblock %} template blocks.

We set it to lxml because it’s a super fast XML/HTML parser.

Warning

compressor.parser.LxmlParser requires the lxml package to work. lxml is a C package and may not be available on all hosting platforms.

COMPRESS_PARSER = 'compressor.parser.LxmlParser'
See also, Django Compressor’s Documentation for COMPRESS_PARSER
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_PARSER
COMPRESS_STORAGE

COMPRESS_STORAGE controls the storage backend that Django Compressor will use when writing out the final compressed files.

We set it to compressor.storage.GzipCompressorFileStorage which is a simple extension of the default file storage sys. It simply creates two copies of each compressed file. One is the regular file and one it a gzip compressed version.

For example, it would create main.ae413.css and main.ae413.css.gz.

This allow a web server (when configured correctly) to server the gzipped version of the file directly to clients that support gzip. It can reduce server load and also can work well with a CDN that may not support on-the-fly gzip compression.

COMPRESS_STORAGE = 'compressor.storage.GzipCompressorFileStorage'
See also, Django Compressor’s Documentation for COMPRESS_STORAGE
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
COMPRESS_OFFLINE

COMPRESS_OFFLINE controls the mode that Django Compressor runs in. We use Django Compressor in offline mode to reduce server load and to ease transition to multiple servers or a CDN.

Note

As an alternative to offline mode you can use online mode. In online mode Django Compressor will build and cache the compressed static files during the request/response cycle. While this mode is simpler to setup initially, it quickly becomes a problem when using multiple servers or a CDN. We avoid any later transition issue by just using offline mode from the start.

In offline mode you have to run manage.py compress before each deploy. This command will parse through your templates and build the cached CSS and JS files.

Compressing the static files in offline mode does have some limitations. You have to specify the context variables that you want available inside {% templatetag openblock %} compress {% templatetag closeblock %} template tags explicitly. See the COMPRESS_OFFLINE_CONTEXT setting.

Note

By default the COMPRESS_OFFLINE_CONTEXT contains only the STATIC_URL context variable.

COMPRESS_OFFLINE = True
See also, Django Compressor’s Documentation for COMPRESS_OFFLINE
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE
COMPRESS_CSS_FILTERS

COMPRESS_CSS_FILTERS is the list of filters that Django Compressor will use when compressing CSS files.

By default we enable three filters.

compressor.filters.css_default.CssAbsoluteFilter parses CSS files for url() properties and replaces relative URLS with absolute ones.

compressor.filters.datauri.CssDataUriFilter parses CSS for images referenced by url() and if the image is smaller than COMPRESS_DATA_URI_MAX_SIZE it will compile the image into a data URI directly inside the CSS file.

Using data URIs instead of referencing images via URLs reduces the number of HTTP requests that the client has to make to render the page. Less HTTP requests means less round-trips and faster page load times.

Also, data URIs can alleviate some of the need of CSS sprite images, because it allows small images to be embedded directly into the CSS file.

Warning

Data URIs aren’t supported in every browser. Most notably IE 6 and 7 don’t support them at all. If support for IE 6 or 7 is important to you, remove compressor.filters.datauri.CssDataUriFilter from the list. Also, more obscure browsers may not support data URIs. Using CSS image sprites many be a good fallback option. For a full list of browsers that support data URIs see http://caniuse.com/datauri.

compressor.filters.cssmin.CSSMinFilter runs the entire CSS file through a CSS minifier to remove whitespace and comments. This reduces the size of the final CSS output.

COMPRESS_CSS_FILTERS = (
    'compressor.filters.css_default.CssAbsoluteFilter',
    'compressor.filters.datauri.CssDataUriFilter',
    'compressor.filters.cssmin.CSSMinFilter',
)
See also, Django Compressor’s Documentation for COMPRESS_CSS_FILTERS
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_CSS_FILTERS
COMPRESS_CSS_HASHING_METHOD

COMPRESS_CSS_HASHING_METHOD controls how Django Compressor determines if a CSS file has new changes. By default it uses the mtime of the files.

By setting it to content we change this to hash the contents of the files. Hashing the contents of the files is slower, but more accurate and works better across multiple servers and/or developer workstations. Also, because we are using Django Compressor in offline mode the slowness really has no effect.

COMPRESS_CSS_HASHING_METHOD = 'content'
See also, Django Compressor’s Documentation for COMPRESS_CSS_HASHING_METHOD
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_CSS_HASHING_METHOD
COMPRESS_DATA_URI_MAX_SIZE

COMPRESS_DATA_URI_MAX_SIZE controls the size of files that will be converted into data URIs inside the CSS files. By default we set it to 30KB to avoid the IE 8 issue.

See compressor.filters.datauri.CssDataUriFilter in the COMPRESS_CSS_FILTERS setting.

Warning

IE 8 doesn’t support data URIs larger than 32KB. IE versions 9+ support data URIs up to 4GB in size.

COMPRESS_DATA_URI_MAX_SIZE = 30 * 1024  # 30KB
See also, Django’s documentation for COMPRESS_DATA_URI_MAX_SIZE
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_DATA_URI_MAX_SIZE
COMPRESS_JS_FILTERS

COMPRESS_JS_FILTERS is the list of filters that Django Compressor will apply to Javascript files. By default we only use one filter.

compressor.filters.closure.ClosureCompilerFilter will pass the contents of the JS files into Google Closure Compiler for JS minification. This minifier requires the Google Closure Compiler binary, see the COMPRESS_CLOSURE_COMPILER_BINARY setting.

COMPRESS_JS_FILTERS = (
    'compressor.filters.closure.ClosureCompilerFilter',
)
See also, Django’s documentation for COMPRESS_JS_FILTERS
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_JS_FILTERS
COMPRESS_CLOSURE_COMPILER_BINARY

COMPRESS_CLOSURE_COMPILER_BINARY tells Django Compressor where to find the Google Closure Compiler binarywhen using the compressor.filters.closure.ClosureCompilerFilter filter.

We include Google Closure Compiler binary with the project distribution at bin/closure_compiler.jar. All you need is Java to run it.

COMPRESS_CLOSURE_COMPILER_BINARY = 'java -jar %s' % os.path.join(
    BIN_ROOT, 'closure_compiler.jar')
See also, Django’s documentation for COMPRESS_CLOSURE_COMPILER_BINARY
https://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_CLOSURE_COMPILER_BINARY

Celery settings

Settings for the celery distributed task queue. Below is the initialization of celery for Django.

import djcelery
djcelery.setup_loader()
CELERY_TIMEZONE

CELERY_TIMEZONE sets the timezone that celery will use. We set it to use the same timezone as Django.

CELERY_TIMEZONE = TIME_ZONE
See also, Celery’s documentation for CELERY_TIMEZONE
http://docs.celeryproject.org/en/latest/configuration.html#celery-timezone
CELERYD_HIJACK_ROOT_LOGGER

Setting CELERYD_HIJACK_ROOT_LOGGER to False tells celery to not override our logging configuration. See the LOGGING setting.

CELERYD_HIJACK_ROOT_LOGGER = False
See also, Celery’s documentation for CELERYD_HIJACK_ROOT_LOGGER
http://docs.celeryproject.org/en/latest/configuration.html#celeryd-hijack-root-logger

Miscellaneous project settings

This is the section where you should put additional project settings. Make sure to document any new settings.

local.py.example

local.py.exmaple is a settings file that extends the base.py settings file. It its meant to be used for local development. A new developer will copy local.py.example to local.py so make sure that the settings in here make sense for local development.

Debug settings

The DEBUG flag controls whether or not Django will operate in DEBUG mode. This should be off when in production.

DEBUG
DEBUG = True
See also, Django’s documentation for DEBUG
https://docs.djangoproject.com/en/1.4/ref/settings/#debug
TEMPLATE_DEBUG

The TEMPLATE_DEBUG flag controls whether or not Django will render tempaltes in DEBUG mode. By default this is set to the same value as DEBUG. This should be off when in production.

TEMPLATE_DEBUG = DEBUG
See also, Django’s documentation for TEMPLATE_DEBUG
https://docs.djangoproject.com/en/1.4/ref/settings/#template-debug
DEBUG_TOOLBAR

The DEBUG_TOOLBAR flag controls whether or not the Django Debug Toolbar is active. This setting meant to make turning on and off the toolbar easy. See DEBUG_TOOLBAR in the Conditional settings section.

DEBUG_TOOLBAR = DEBUG
COMPRESS_ENABLED

The COMPRESS_ENABLED flag controls whether or not Django Compressor serves the compressed content or not. By default this option is set to the same as DEBUG. You can enable this while DEBUG remains False to test the Django Compression output.

COMPRESS_ENABLED = DEBUG

Database settings

DATABASES

DATABASES is a dictionary mapping the different databases that Django will use.

By default we use PostgreSQL as the default database. PostgreSQL is a great RDMS. It supports a ton of features and is generally better than MySQL.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': '{{ project_name }}',
        'USER': '{{ project_name }}',
        'PASSWORD': '',
        'PORT': '',
        'HOST': '',
    }
}
See also, Django’s documentation for DATABASES
https://docs.djangoproject.com/en/1.4/ref/settings/#databases

Cache settings

CACHES

CACHES is a dictionary mapping the caches that Django will use.

By default we just use a dummy cache that accepts any writes, but ignores them and always returns misses for cache reads.

We set KEY_PREFIX to the name of the project to reduce the chance of cache key collisions.

In production this should be set to use Memcached.

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
        'KEY_PREFIX': '{{ project_name }}'
    }
}
See also, Django’s documentation for CACHES
https://docs.djangoproject.com/en/1.4/ref/settings/#caches

Email settings

EMAIL_HOST

EMAIL_HOST is the host that Django will connect to to send email. If you’re just going to send emails directly and not use a email delivery service you should install a local email server, which Django can offload email handling to. Postfix is a good option.

EMAIL_HOST = 'localhost'
See also, Django’s documentation for EMAIL_HOST
https://docs.djangoproject.com/en/1.4/ref/settings/#email-host

Logging settings

LOGGING

LOGGING is a dictionary configuration for the Python logging system.

version

This is the version of the dictionary schema. 1 is the only valid option at this point.

disable_existing_loggers

Setting this to True will disable any previously registered loggers and only use the loggers from this configuration.

formatters

The formatters are used to format log entires for the handler.

verbose

This is the verbose format for the console logger.

The Python code:

logger = logging.getLogger('myapp.tasks')
logger.info('the task with id #%d failed', 101)

Produces the log message:

[2012-11-20 12:53:58,503] [INFO] [myapp.tasks] the task with id #101 failed

json

The JSON formatter outputs all the log records fields using JSON. This makes it a breeze to parse the log files later.

The schema used is defined in {{ project_name }}.logging.utils.formatters.JSONFormatter.

One of the handy features of the JSON formatter is that it will output all of the extra logging information by default without you having to specify it in the format beforehand.

Note

By default the file produced isn’t valid JSON. It’s just a file with a valid JSON object on each line. You can process the JSON log file several ways.

You can add commas at the end of each line except the last line and add brackets [ ] at the beginning and end of file. This makes the whole file valid JSON and you can just run json.load('app.json.log') to load all the entries.

The other option you have is to parse the file line by line. For example:

with open('app.json.log') as logfile:
    for line in logfile:
        logline = json.loads(line)

I tend to prefer this method because it doesn’t require creating objects for the entire JSON file in memory before you can do any processing.

Note

Just because the file contains JSON data doesn’t mean that you can only process it using JSON tools.

The file is also just a text file with one log entry per line. This means that you can still do processing with all the normal text manipulation and filtering tools that you are used to. grep still works just fine for filtering.

Warning

The JSON formatter is quite verbose and stores a lot of data by default. Each log line will be at between 500 - 1,000 bytes in length.

Disk space is cheap and verbose logging can be critical when trying to debug a production system.

Normally this won’t be a problem because it still means you can store about 100,000 log messages per 100MB of disk space. Also, because of the verbosity of JSON, the log files will compress down really well with a 15-30x compression ratio. Meaning you could store 3,000,000 log messages per 100MB when compressed.

The Python code:

logger = logging.getLogger('myapp.tasks')
logger.info('the task with id #%d failed', 101, extra={'ip': '127.0.0.1', 'id': 10)

Produces the log message:

Note

The message here is shown as multiple lines for readability, normally the log message will appear all on one line.

{
    "extra": {
        "ip": "127.0.0.1",
        "id": 10
    },
    "process": {
        "process": 9168,
        "processName": "MainProcess",
        "threadName": "MainThread",
        "thread": 140735211397504
    },
    "file": {
        "funcName": "main",
        "pathname": "test.py",
        "lineno": 116,
        "module": "test",
        "filename": "test.py"
    },
    "time": {
        "relativeCreated": 13.112068176269531,
        "asctime": "2012-11-21T10:02:06.612837Z",
        "created": 1353492126.612837
    },
    "logger": {
        "levelno": 10,
        "name": "main",
        "levelname": "DEBUG"
    },
    "message": {
        "msg": "the task with id #%d failed",
        "message": "the task with id #101 failed",
        "args": [101]
    }
}
filters

Filters filter log records before they are sent to the handler.

require_debug_false

Only lets log records through when DEBUG is set to False. This is a handy filter to use when you only want a handler to work in production.

handlers

Handlers decide how formatted log records are handled. They can write log records to disk or send them out over the network. There are many built in handlers, you can see them all at http://docs.python.org/2/library/logging.handlers.html.

null

The null handler just discards all log records. It’s useful when you need a handler that does nothing.

console

The console handler prints log records out to stderr using the verbose formatter.

rotating_file

The rotating_file handler writes log records out to the file var/log/app.json.log using the json formatter.

Additionally it will rotate the log file when it reaches 50MB in size. It will keep one file back as for some history. This means that it will use a maximum of 100MB for logging.

watched_file

The watched_file handler writes log records out to the file var/log/app.json.log using the JSON formatter, additionally it will reopen the file handle if the file is moved.

This is useful when you are using programs like logrotate to do automatic log rotation and compression. Once the file is rotated this handler will a new file and continue writing out log records.

mail_admins

The mail_admins handler will email the ADMINS of the site with the log record.

This is mostly useful as a poor mans exception and error reporting.

By default this handler will only log records that are ERROR level or higher and will only log records when DEBUG is False.

loggers

Here is where you can tie specific loggers to handlers. By default we only put handlers on the root logger, but you can be more selective for your own needs.

root

We hook the root logger up to the mail_admins, console and rotating_file handlers by default.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'verbose': {
            'format': '[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s',
        },
        'json': {
            '()': '{{ project_name }}.utils.logging.formatters.JSONFormatter',
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
    },
    'handlers': {
        'null': {
            'class': 'django.utils.log.NullHandler',
        },
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
        'rotating_file': {
            'level': 'DEBUG',
            'filters': [],
            'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'json',
            'encoding': 'utf8',
            'filename': os.path.join(VAR_ROOT, 'log', 'app.json.log'),
            'maxBytes': (1024 * 1024) * 10,  # 50MB
            'backupCount': 1,
        },
        'watched_file': {
            'level': 'DEBUG',
            'filters': [],
            'class': 'logging.handlers.WatchedFileHandler',
            'formatter': 'json',
            'encoding': 'utf8',
            'filename': os.path.join(VAR_ROOT, 'log', 'app.json.log'),
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
    },
    'root': {
        'handlers': ['mail_admins', 'console', 'rotating_file'],
        'level': 'DEBUG',
    },
    'loggers': {
        # Define more specific logger here
    },
}
See also, Django’s documentation for LOGGING
https://docs.djangoproject.com/en/1.4/ref/settings/#logging

Security settings

SECRET_KEY

The SECRET_KEY is a string of characters that Django will use in it’s security mechanisms (like password hashing) to improve security.

It should be random, secret, and static. You should use a different one for each environment.

SECRET_KEY = 'some auto-generated random characters'
See also, Django’s documentation for SECRET_KEY
https://docs.djangoproject.com/en/1.4/ref/settings/#secret-key
SSL

If you are using SSL for your entire site you should set this to True, otherwise leave it at False. It changes a bunch of settings to take advantage of your SSL secured site. See Conditional SSL for more information.

SSL = False

HTTP proxy settings

SECURE_PROXY_SSL_HEADER

SECURE_PROXY_SSL_HEADER is the header and value of the header that Django should use to determine if the request was made over HTTPS.

Most Django sites sit behind a reverse proxy (like Nginx) that does HTTP and SSL negotiation for them. This makes the site scale better and be more robust. However it also makes it impossible for Django to know if a request was made securely over SSL.

Most web servers can be configured to set a header when the site is accessed over SSL. This setting controls which header Django can look at to get that information.

Warning

Using this setting can open up your site to a security issue. If you turn this on you’ll need to confirm that end users can control the value of the header that your using. For more information see the warning that Django gives about this setting.

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
See also, Django’s documentation for SECURE_PROXY_SSL_HEADER
https://docs.djangoproject.com/en/1.4/ref/settings/#secure-proxy-ssl-header

Celery settings

Celery settings that should be defined differently for each environment.

BROKER_URL

BROKER_URL is the configuration URL for the celery message broker. By default we set it to use redis on localhost.

BROKER_URL = 'redis://'
See also, Celery’s documentation for BROKER_URL
http://docs.celeryproject.org/en/latest/configuration.html#broker-url
CELERY_RESULT_BACKEND

CELERY_RESULT_BACKEND is the configuration URL for the celery results backend. By default we set it to use redis on localhost.

CELERY_RESULT_BACKEND = 'redis://'
See also, Celery’s documentation for CELERY_RESULT_BACKEND
http://docs.celeryproject.org/en/latest/configuration.html#celery-result-backend
CELERY_ALWAYS_EAGER

CELERY_ALWAYS_EAGER controls when the tasks are executed. Setting it to True disabled out of process execution and the tasks run like normal Python functions.

We set it to the same as DEBUG so that when developing and testing you don’t have to wait for tasks to queue and run asynchronously.

CELERY_ALWAYS_EAGER = DEBUG
See also, Celery’s documentation for CELERY_ALWAYS_EAGER
http://docs.celeryproject.org/en/latest/configuration.html#celery-always-eager
CELERY_EAGER_PROPAGATES_EXCEPTIONS

CELERY_EAGER_PROPAGATES_EXCEPTIONS controls how exception handling works when CELERY_ALWAYS_EAGER is set to True.

CELERY_EAGER_PROPAGATES_EXCEPTIONS is set to True exceptions that are raised inside tasks will propagate up to your code and cause 500 errors. This is what you want when developing so that exceptions don’t pass silently. Also this is needed during tests.

By default we also set this to be True when CELERY_ALWAYS_EAGER is True.

CELERY_EAGER_PROPAGATES_EXCEPTIONS = CELERY_ALWAYS_EAGER
See also, Celery’s documentation for CELERY_EAGER_PROPAGATES_EXCEPTIONS
http://docs.celeryproject.org/en/latest/configuration.html#celery-eager-propagates-exceptions

Conditional settings

These settings are controlled via flags earlier in the file. Here we define what those flags actually do.

DEBUG_TOOLBAR

When DEBUG_TOOLBAR is True we add debug-toolbar to the installed apps and middleware settings. This enables Django Debug Toolbar.

if DEBUG_TOOLBAR:
    INSTALLED_APPS += ('debug_toolbar',)
    MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)

SSL

If SSL is True we enable a bunch of additional settings to improve our use of SSL.

if SSL:
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    SECURE_SSL_REDIRECT = True
    WAFFLE_SECURE = True
    # SECURE_HSTS_SECONDS =

Setting SESSION_COOKIE_SECURE to True adds the secure flag to the session cookie. This means that the browser will only send that cookie when the request it made via SSL.

SESSION_COOKIE_SECURE = True
See also, Django’s documentation for SESSION_COOKIE_SECURE
https://docs.djangoproject.com/en/1.4/ref/settings/#session-cookie-secure

Setting CSRF_COOKIE_SECURE to True adds the secure flag to the CSRF cookie. This means that the browser will only send that cookie when the request it made via SSL.

CSRF_COOKIE_SECURE = True
See also, Django’s documentation for CSRF_COOKIE_SECURE
https://docs.djangoproject.com/en/1.4/ref/settings/#csrf-cookie-secure
SECURE_SSL_REDIRECT

Setting SECURE_SSL_REDIRECT to True enables Django Secure to redirect any requests that don’t come via SSL to the SSL version of the URL.

SECURE_SSL_REDIRECT = True
See also, Django Secure’s documentation for SECURE_SSL_REDIRECT
http://django-secure.readthedocs.org/en/v0.1.2/settings.html#secure-ssl-redirect
WAFFLE_SECURE

Setting WAFFLE_SECURE to True adds the secure flag to the waffle cookie. This means that the browser will only send that cookie when the request it made via SSL.

WAFFLE_SECURE = True
See also, Django Waffle’s documentation for WAFFLE_SECURE
http://waffle.readthedocs.org/en/latest/usage.html#global-settings
SECURE_HSTS_SECONDS

Setting SECURE_HSTS_SECONDS to a non-zero integer value, causes Django Secure to set the HTTP Strict Transport Security header on all responses that do not already have that header.

This will force the browser to only make SSL connections to that domain for the number of seconds you have listed.

You should set this to a low number while testing SSL, and then raise it to a higher number after testing is complete.

You can find out more HSTS on Wikipedia.

SECURE_HSTS_SECONDS = 120
See also, Django Secure’s documentation for SECURE_HSTS_SECONDS
http://django-secure.readthedocs.org/en/v0.1.2/settings.html#secure-hsts-seconds

Miscellaneous project settings

This is a section for miscellaneous project specific settings. Each setting should be documented in full.

Additional Environments Settings

Each different environment that you application runs in should have a different settings file based on local.py.example.