Apache mod_wsgi config
November 21, 2009
mod_wsgi is now the recommended method for deploying your django sites. This shows how to set up a django site using mod_wsgi on apache, and have the site auto-reload when the source files change.
Here's what you need:
site-wsgi.py
import os, sys sys.path.append('/path/to/deploy/directory') os.environ['DJANGO_SETTINGS_MODULE'] = 'site.settingslive' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() import site.monitor site.monitor.start(interval=1.0)
monitor.py
Use this as is, it doesn't need modifying per host.
import os import sys import time import signal import threading import atexit import Queue _interval = 1.0 _times = {} _files = [] _running = False _queue = Queue.Queue() _lock = threading.Lock() def _restart(path): _queue.put(True) prefix = 'monitor (pid=%d):' % os.getpid() print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path) print >> sys.stderr, '%s Triggering process restart.' % prefix os.kill(os.getpid(), signal.SIGINT) def _modified(path): try: # If path doesn't denote a file and were previously # tracking it, then it has been removed or the file type # has changed so force a restart. If not previously # tracking the file then we can ignore it as probably # pseudo reference such as when file extracted from a # collection of modules contained in a zip file. if not os.path.isfile(path): return path in _times # Check for when file last modified. mtime = os.stat(path).st_mtime if path not in _times: _times[path] = mtime # Force restart when modification time has changed, even # if time now older, as that could indicate older file # has been restored. if mtime != _times[path]: return True except: # If any exception occurred, likely that file has been # been removed just before stat(), so force a restart. return True return False def _monitor(): while 1: # Check modification times on all files in sys.modules. for module in sys.modules.values(): if not hasattr(module, '__file__'): continue path = getattr(module, '__file__') if not path: continue if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']: path = path[:-1] if _modified(path): return _restart(path) # Check modification times on files which have # specifically been registered for monitoring. for path in _files: if _modified(path): return _restart(path) # Go to sleep for specified interval. try: return _queue.get(timeout=_interval) except: pass _thread = threading.Thread(target=_monitor) _thread.setDaemon(True) def _exiting(): try: _queue.put(True) except: pass _thread.join() atexit.register(_exiting) def track(path): if not path in _files: _files.append(path) def start(interval=1.0): global _interval if interval < _interval: _interval = interval global _running _lock.acquire() if not _running: prefix = 'monitor (pid=%d):' % os.getpid() print >> sys.stderr, '%s Starting change monitor.' % prefix _running = True _thread.start() _lock.release()
Apache virtual host
This is optimised for a host with very little memory, and low traffic websites.
<VirtualHost *:80> ServerAdmin email.host.net ServerName www.host.net ServerAlias host.net WSGIDaemonProcess sitename user=UserToRunAs group=GroupToRunAs processes=5 threads=5 stack-size=524288 WSGIProcessGroup sitename CustomLog /path/to/log.log vhost_combined WSGIScriptAlias / /path/to/site-wsgi.py Alias /site_media/ "/path/to/site_media/" Alias /media/ "/path/to/django/contrib/admin/media/" <Directory /path/to/site_media/> Order allow,deny Allow from all Options -Indexes </Directory> </VirtualHost>