The default for Apache/mod_wsgi is to only load application code on first request to a process which requires that applications. So, first step is to configure mod_wsgi to preload your code when the process starts and not only the first request. This can be done in mod_wsgi 2.X using the WSGIImportScript directive.
Presuming daemon mode, which is better option anyway, this means you would have something like:
# Define process group.
WSGIDaemonProcess django display-name=%{GROUP}
# Mount application.
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi
# Ensure application preloaded on process start. Must specify the
# process group and application group (Python interpreter) to use.
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
process-group=django application-group=%{GLOBAL}
<Directory /usr/local/django/mysite/apache>
# Ensure application runs in same process group and application
# group as was preloaded into on process start.
WSGIProcessGroup django
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
When you have made a code change, instead of touch the WSGI script file, which is only checked on the next request, send a SIGINT signal to the processes in the daemon process group instead.
With the 'display-name' option to WSGIDaemonProcess you can identify which processes by using BSD style 'ps' program. With 'display-name' set to '%{GROUP}', the 'ps' output should show '(wsgi:django)' as process name. Identify the process ID and do:
kill -SIGINT pid
Swap 'pid' with actual process ID. If more than one process in daemon process group, send signal to all of them.
Not sure if 'killall' can be used to do this in one step. I had problem with doing it on MacOS X.
In mod_wsgi 3.X the configuration can be simpler and can use instead:
# Define process group.
WSGIDaemonProcess django display-name=%{GROUP}
# Mount application and designate which process group and
# application group (Python interpreter) to run it in. As
# process group and application group named, this will have
# side effect of preloading application on process start.
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi \
process-group=django application-group=%{GLOBAL}
<Directory /usr/local/django/mysite/apache>
Order deny,allow
Allow from all
</Directory>
That is, no need to use separate WSGIImportScript directive as can specific process group and application group as arguments to WSGIScriptAlias instead with side effect that it will preload application.