When we work in a web project it’s usual to have a devlopment version and a production version that only differ in some configuration parameters (database, user authentication, file paths…). Usually, the development version is deployed from the version control repository, and you have to tune some settings before restarting the service. With RoR you got that for free but it’s a feature I find lacking in django. Until today.
I use apache for serving the django apps through mod_pyhton, but I test the development version with the server included in the framework. We will use a system environment variable to select the appropiate settings file. We will call this variable DJANGO_SETTINGS_ENVIRONMENT, and we will set it up in the apache-python configuration block using the SetEnv directive. This is an example configuration:
<Location "/djangoproject"> SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE djangoproject.settings SetEnv DJANGO_SETTINGS_ENVIRONMENT production PythonOption django.root /djangoproject PythonInterpreter djangoproject PythonPath "['/var/www/django/', '/var/www'] + sys.path" </Location>
Now, we have to detect the parameters we suspect that will change between configurations, and move all these params from the main settings.py file to two separated files. I created a “settings” folder in the project root, and there I laid the two configuration files:
djangoproject\ settings.py settings\ development.py production.py
Next we modify settings.py to include the sub-configuration file for the selected environment. In order to do this, I used the execfile() function (I don’t know if there’s a better suited function to include code in python :P), and added the following files to my settings.py file. You have to note that if you have global parameters that must be known by the parameters defined inside the sub-configuration files, you have to declare them prior to these lines!
import os # this line should be included always to make our project "path-relative" ROOT_PATH = os.path.abspath(os.path.dirname(__file__)) DEBUG = True TEMPLATE_DEBUG = DEBUG # include sub-configuration settings. Default environment is 'development' DJANGO_SETTINGS_ENVIRONMENT = os.environ.get('DJANGO_SETTINGS_ENVIRONMENT') or 'development' execfile('%s/settings/%s.py' % (ROOT_PATH, DJANGO_SETTINGS_ENVIRONMENT))
Done. Now we can deploy for production the same project we were working with under development, but using different settings for each environment.