Reputation: 935
I have many identical database instances
I want my Django settings to be able to chose any one of these with minimal efforts. I don't want to keep multiple setting files.
I know I can configure them like this but how to switch to anyone other than the default.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'HOST': 'localhost'
},
'staging': {
'ENGINE': 'django.db.backends.sqlite3',
'HOST': 'staging.server.com'
},
'production': {
'ENGINE': 'django.db.backends.sqlite3',
'HOST': 'www.server.com'
}
}
Upvotes: 0
Views: 2049
Reputation: 77281
[update]
For config/code separation I'm using a project called django-decouple instead of rolling my own stuff, the rationale of the original answer remains valid.
[original answer]
I recommend using environment variables instead of if/elif chains and/or includes. The main reasons are:
For example:
DATABASES = {
'default': {
'ENGINE': os.environ.get('DB_NAME', 'django.db.backends.sqlite3'),
'NAME': os.environ.get('DB_NAME', 'some_default'),
'USER': os.environ.get('DB_USER', ''),
'PASSWORD': os.environ.get('DB_PASS', ''),
'HOST': os.environ.get('DB_HOST', ''),
'PORT': '',
}
}
Please read "the twelve factors app" for a longer explanation on the principles behind this practice and "stop writing settings files" for a practical approach to Django settings.
I also recommend using virtualenv. Some tips:
/var/lib/python-virtualenvs
workon project_name
when you want to work at the projectI use a wsgi.py
like this:
import os
import site
import sys
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(APP_ROOT)
PROJECT_NAME = os.path.basename(APP_ROOT)
INSTANCE_NAME = os.path.basename(ROOT)
VENV = '/var/lib/python-virtualenvs/{}/'.format(INSTANCE_NAME)
# Add the site-packages of the chosen virtualenv to work with
site.addsitedir(VENV + 'lib/python2.7/site-packages')
# Add the app's directory to the PYTHONPATH
sys.path.append(ROOT)
# Activate your virtual env
activate_env=os.path.expanduser(VENV + "bin/activate_this.py")
execfile(activate_env, dict(__file__=activate_env))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", PROJECT_NAME + ".settings")
from django.core.wsgi import get_wsgi_application
_application = get_wsgi_application()
def application(environ, start_response):
os.environ['DEBUG'] = environ['DEBUG']
os.environ['DB_NAME'] = environ['DB_NAME']
os.environ['DB_PASS'] = environ['DB_PASS']
os.environ['DB_HOST'] = environ['DB_HOST']
os.environ['DB_USER'] = environ['DB_USER']
return _application(environ, start_response)
Upvotes: 2
Reputation: 935
So I've been reading the book Two Scoops of Django and the whole chapter 5 is based upon this issue. This chapter, Settings and Requirement Files, answers all of my questions. This chapter is based upon Jacob Kaplan-Moss' The Best (and worst) of Django talk at OSCON 2011. See page 47 and onwards of the slide.
Basically, the idea is to use multiple settings files i.e., settings/base.py, settings/local.py, settings/production.py etc. And to use the proper one while launching the server using the --settings switch.
Upvotes: 0
Reputation: 935
I found a way but I am not sure if this is the proper way to do it. Please comment.
I have the main settings.py and the DATABASES setting in it look like...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'HOST': 'www.server.com'
}
}
And at the end of this file, I have the following code...
# Load the local overrides if there are any.
try:
from settings_local import *
except ImportError, e:
pass
Then I have a settings_local.py file in the same location, but ignored by Git, on my local environment as follows...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'HOST': 'localhost'
}
}
This allows my application to connect to the production database server if there is no settings_local.py file in the same directory as settings.py, and to the local (or staging) database if this file exists.
Upvotes: 0