If you’ve progressed beyond the exploration phase in your Django journey, you’ve probably come to the point where, at the least, you would like to use one database during your development, and another, once published to your production system. You may even want to
The beauty of Django, and it’s settings, is that it is itself merely a python object, specifically a python module. The settings module gets executed once upon initialization of the web application. One of my first attempts at segmenting the settings was by checking the hostname or host IP address of the machine running the web application server — this is independent of the method of running Django (development server, mod_wsgi, etc).
This implementation looked something like this:
import socket MACHINE = socket.gethostname().lower() DEBUG_MACHINES = ['test-machine'] DEBUG = MACHINE in DEBUG_MACHINES if DEBUG: DATABASE_HOST = 'localhost' else: DATABASE_HOST = 'live-mysql-server' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'database', 'USER': 'username', 'PASSWORD': 'password', 'HOST': DATABASE_HOST, 'PORT': '', } }
I get the hostname of the machine, check if it is in a known list of debug (development) machines, setting the DEBUG setting to True. The database hostname is then chosen based on being in debug mode or not. If you need a hassle-free wordpress hosting option? you might want to check the link, wordrpress hosting is one of the easiest one to use.
This approach works fine, but requires keeping track of IP addresses, and essentially locks one machine into a single role. I eventually wanted to use one machine for both development and testing purposes, and a second machine as the actual live system. For this, I took more flexible approach — using environment variables to determine the mode that I wanted. I was happy with three modes: DEBUG, TESTING, and LIVE. I decide to use an environment variable, APP_MODE. My settings.py then looked like:
import os APP_MODE = os.environ.get('APP_MODE', 'DEBUG') ; APP_MODE = APP_MODE.upper() if not APP_MODE in ('DEBUG','TESTING','LIVE'): APP_MODE = 'DEBUG' DEBUG = APP_MODE not in ('LIVE') if MG_MODE == 'LIVE': DATABASE_NAME = 'database' DATABASE_HOST = 'live-mysql-server' pass elif MG_MODE == 'TESTING': DATABASE_NAME = 'database-testing' DATABASE_HOST = 'localhost' else: DATABASE_NAME = 'database-debug' DATABASE_HOST = 'localhost' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': DATABASE_NAME, 'USER': 'username', 'PASSWORD': 'password', 'HOST': DATABASE_HOST, 'PORT': '', } }
Now, whenever the Django instance is ran with no explicit environment variables, it is in DEBUG mode. If we want to explicitly run the development in, say, TESTING mode. We run the server as:
$ APP_MODE=TESTING python manage.py runserver
The troublesome part was getting the production Apache+mod_wsgi instance to run in LIVE mode. Setting the environment variable from the <VirtualHost>
section was easy:
SetEnv APP_MODE LIVE
The issue, however is that the default WSGI Django setup does not (seem) to automatically pass external environmental variables to the Django application object instance. I found it necessary to subclass and enhance the application created to pass in just the environment variables that I was interested in. This gave me a wsgi.py file somewhat like this:
import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings") # create basic handler from django.core.wsgi import get_wsgi_application _application = get_wsgi_application() # wrap handler with our own callable def application(environ, start_response): # copy APP_ env variables into process for k in environ.keys(): if not k.startswith('APP_'): continue os.environ[k] = environ[k] # return base handler return _application(environ, start_response)
This checks for all environment variables with a prefix of “APP_” and adds them to the environment of the application.
With that I can now setup one or more <VirtualHost>
sections with alternate APP_MODEs, or run python manage.py syncdb
to create the production database. The settings varied are entirely up to the developer, as is how complex the logic is. It is important to remember that settings.py is not specific to individual HTTP requests.