What is the recommended way of handling settings for local development and the production server? Some of them (like constants, etc) can be changed/accessed in both, but s
I manage my configurations with the help of django-split-settings.
It is a drop-in replacement for the default settings. It is simple, yet configurable. And refactoring of your exisitng settings is not required.
Here's a small example (file example/settings/__init__.py
):
from split_settings.tools import optional, include
import os
if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
include(
'components/default.py',
'components/database.py',
# This file may be missing:
optional('local_settings.py'),
scope=globals()
)
That's it.
I wrote a blog post about managing django
's settings with django-split-sttings
. Have a look!
1 - Create a new folder inside your app and name settings to it.
2 - Now create a new __init__.py
file in it and inside it write
from .base import *
try:
from .local import *
except:
pass
try:
from .production import *
except:
pass
3 - Create three new files in the settings folder name local.py
and production.py
and base.py
.
4 - Inside base.py
, copy all the content of previous settings.py
folder and rename it with something different, let's say old_settings.py
.
5 - In base.py change your BASE_DIR path to point to your new path of setting
Old path->
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
New path ->
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
This way, the project dir can be structured and can be manageable among production and local development.
Making multiple versions of settings.py is an anti pattern for 12 Factor App methodology. use python-decouple or django-environ instead.
I use a variation of what jpartogi mentioned above, that I find a little shorter:
import platform
from django.core.management import execute_manager
computername = platform.node()
try:
settings = __import__(computername + '_settings')
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
Basically on each computer (development or production) I have the appropriate hostname_settings.py file that gets dynamically loaded.
I differentiate it in manage.py and created two separate settings file: local_settings.py and prod_settings.py.
In manage.py I check whether the server is local server or production server. If it is a local server it would load up local_settings.py and it is a production server it would load up prod_settings.py. Basically this is how it would look like:
#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager
ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
try:
import local_settings # Assumed to be in the same directory.
settings = local_settings
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
else:
try:
import prod_settings # Assumed to be in the same directory.
settings = prod_settings
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
I found it to be easier to separate the settings file into two separate file instead of doing lots of ifs inside the settings file.
I use a slightly modified version of the "if DEBUG" style of settings that Harper Shelby posted. Obviously depending on the environment (win/linux/etc.) the code might need to be tweaked a bit.
I was in the past using the "if DEBUG" but I found that occasionally I needed to do testing with DEUBG set to False. What I really wanted to distinguish if the environment was production or development, which gave me the freedom to choose the DEBUG level.
PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
PRODUCTION = True
else:
PRODUCTION = False
DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG
# ...
if PRODUCTION:
DATABASE_HOST = '192.168.1.1'
else:
DATABASE_HOST = 'localhost'
I'd still consider this way of settings a work in progress. I haven't seen any one way to handling Django settings that covered all the bases and at the same time wasn't a total hassle to setup (I'm not down with the 5x settings files methods).