Preparing Your Django Application for Production
Getting started with Django is quick and easy. By default Django comes configured for a local development environment, and while you can create elaborate web applications that work on your local machine, at some point you’ll want to get your web application production-ready.
Many of the default settings in a Django application can be left as-is, but there are a few settings that almost certainly need to change before your application is ready for production.
In this article we’ll cover common changes required to get your application configured for a production environment. For the demonstration purposes in this article, we’ll assume a Django application called `foo` created with the Django-admin startproject command.
Managing environments with the DJANGO_SETTINGS_MODULE
When you’re developing a production application, you typically will have multiple environments in which the application will run. Developers will need to run the application locally, and you may have a number of staging environments for testing purposes, as well as a production environment that will be available to the public. Each of these environments will have a configuration specific to that environment.
Using DJANGO_SETTINGS_MODULE
Django provides a convenient way of specifying different settings files to use for your application by using the DJANGO_SETTINGS_MODULE
environment variable. One option for managing your various environments is to create a different configuration file for each of your environments and use DJANGO_SETTINGS_MODULE
to specify the file for your environment.
The advantage here is that you can easily see what the exact configuration is for each environment, and it can be a convenient way to manage all your configuration in one place.
There are, however, a number of drawbacks to this approach:
- Configuration changes are tied to your application code.
- Sensitive access keys and passwords are saved as plain text in your code.
- You will need a file per environment which makes it complicated to manage if you want to be able to dynamically create or destroy environments.
Shared settings
If you choose to have multiple settings files, consider putting the shared configuration into another file and importing it into your environment-specific files. For example, let’s say that we have the configuration that’s common to all of our environments in a file called shared_settings.py in the foo/ directory.
We could then create a local_settings.py file that looks something like this:
ENV = 'local'
DEBUG = True
from .shared_settings import *
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Using environment variables
Another option for configuring your Django application is to use environment variables.
Using environment variables allows you to decouple your application configuration from your application code. This means you can easily run your application in as many environments as you’d like, without having to modify your application code.
It also allows you to inject sensitive information required to configure your application and easily store it securely elsewhere.
You could still have multiple settings files if you wish to avoid if-statements when dealing with environment-specific configurations. For example, you could have a local_settings.py for local development and a remote_settings.py for when your application is being hosted on a remote server.
In either case, using environment variables gives you added flexibility and security. As an example, let’s take a look at what a remote_settings.py might look like:
import os
ENV = os.getenv('ENV')
DEBUG = False
from .default_settings import *
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME', 'foo'),
'USER': os.getenv('DB_USER', 'foo'),
'PASSWORD': os.getenv('DB_PASS', 'bar'),
'HOST': os.getenv('DB_HOST', '127.0..0.1'),
'PORT': os.getenv('DB_PORT', '5432'),
}
}
Here, we have decided that our application will work with PostgreSQL across all environments, but we allow environment variables to be used to configure where and how the database will be accessed.
Configuring for production
Django allows for many different components to be configured, replaced or excluded entirely, but the majority of the defaults can work in most web applications.
A number of the default settings, however, are designed to allow for you to start with local development right away and are not appropriate for most production environments. Let’s take a look at the main pieces that need to change in order to get a simple web application ready for production.
DEBUG
flag
For development and debugging purposes, Django has a debug flag for turning certain features that are useful for development on and off for production, as some features could be a security concern. Whenever you’re making your application ready for production, you should set DEBUG = False
.
ALLOWED_HOSTS
When you set DEBUG = False
, Django checks that the HTTP Host header matches one of the entries in your ALLOWED_HOSTS
setting. This is a security measure meant to protect against HTTP Host header attacks. This setting needs to be set to allow the host name where you are making your application available. If you’re dynamically creating environments, you may want to allow hosts to be specified as environment variables so that they can be injected into the application as it launches.
Here is an example of what this might look like in remote_settings.py
import os
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'mydefault.com').split(',')
Databases
Django provides an ORM that lets you define data models, allowing you to access persisted data without worrying about what database backend the data will be stored in.
Back to Top