Django: How to manage development and production settings?

This is how I do it in 6 easy steps:

  1. Create a folder inside your project directory and name it settings.

    Project structure:

    myproject/
           myapp1/
           myapp2/              
           myproject/
                  settings/
    
  2. Create four python files inside of the settings directory namely __init__.py, base.py, dev.py and prod.py

    Settings files:

    settings/
         __init__.py
         base.py
         prod.py
         dev.py 
    
  3. Open __init__.py and fill it with the following content:

    init.py:

    from .base import *
    # you need to set "myproject = 'prod'" as an environment variable
    # in your OS (on which your website is hosted)
    if os.environ['myproject'] == 'prod':
       from .prod import *
    else:
       from .dev import *
    
  4. Open base.py and fill it with all the common settings (that will be used in both production as well as development.) for example:

    base.py:

    import os
    ...
    INSTALLED_APPS = [...]
    MIDDLEWARE = [...]
    TEMPLATES = [{...}]
    ...
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    MEDIA_ROOT = os.path.join(BASE_DIR, '/path/')
    MEDIA_URL = '/path/'
    
  5. Open dev.py and include that stuff which is development specific for example:

    dev.py:

    DEBUG = True
    ALLOWED_HOSTS = ['localhost']
    ...
    
  6. Open prod.py and include that stuff which is production specific for example:

    prod.py:

    DEBUG = False
    ALLOWED_HOSTS = ['www.example.com']
    LOGGING = [...]
    ...
    

Update

As ANDRESMA suggested in comments. Update BASE_DIR in your base.py file to reflect your updated path by adding another .parent to the end. For example:

BASE_DIR = Path(__file__).resolve().parent.parent.parent

By default use production settings, but create a file called settings_dev.py in the same folder as your settings.py file. Add overrides there, such as DEBUG=True.

On the computer that will be used for development, add this to your ~/.bashrc file:

export DJANGO_DEVELOPMENT=true

At the bottom of your settings.py file, add the following.

# Override production variables if DJANGO_DEVELOPMENT env variable is set
if os.environ.get('DJANGO_DEVELOPMENT'):
    from settings_dev import *  # or specific overrides

(Note that importing * should generally be avoided in Python)

By default the production servers will not override anything. Done!

Compared to the other answers, this one is simpler because it doesn't require updating PYTHONPATH, or setting DJANGO_SETTINGS_MODULE which only allows you to work on one django project at a time.


I usually have one settings file per environment, and a shared settings file:

/myproject/
  settings.production.py
  settings.development.py
  shared_settings.py

Each of my environment files has:

try:
    from shared_settings import *
except ImportError:
    pass

This allows me to override shared settings if necessary (by adding the modifications below that stanza).

I then select which settings files to use by linking it in to settings.py:

ln -s settings.development.py settings.py

The DJANGO_SETTINGS_MODULE environment variable controls which settings file Django will load.

You therefore create separate configuration files for your respective environments (note that they can of course both import * from a separate, "shared settings" file), and use DJANGO_SETTINGS_MODULE to control which one to use.

Here's how:

As noted in the Django documentation:

The value of DJANGO_SETTINGS_MODULE should be in Python path syntax, e.g. mysite.settings. Note that the settings module should be on the Python import search path.

So, let's assume you created myapp/production_settings.py and myapp/test_settings.py in your source repository.

In that case, you'd respectively set DJANGO_SETTINGS_MODULE=myapp.production_settings to use the former and DJANGO_SETTINGS_MODULE=myapp.test_settings to use the latter.


From here on out, the problem boils down to setting the DJANGO_SETTINGS_MODULE environment variable.

Setting DJANGO_SETTINGS_MODULE using a script or a shell

You can then use a bootstrap script or a process manager to load the correct settings (by setting the environment), or just run it from your shell before starting Django: export DJANGO_SETTINGS_MODULE=myapp.production_settings.

Note that you can run this export at any time from a shell — it does not need to live in your .bashrc or anything.

Setting DJANGO_SETTINGS_MODULE using a Process Manager

If you're not fond of writing a bootstrap script that sets the environment (and there are very good reasons to feel that way!), I would recommend using a process manager:

  • Supervisor lets you pass environment variables to managed processes using a program's environment configuration key.
  • Honcho (a pure-Python equivalent of Ruby's Foreman) lets you define environment variables in an "environment" (.env) file.

Finally, note that you can take advantage of the PYTHONPATH variable to store the settings in a completely different location (e.g. on a production server, storing them in /etc/). This allows for separating configuration from application files. You may or may not want that, it depends on how your app is structured.

Tags:

Python

Django