Running multiple Django projects within Apache, sys.path being over written

I have been trying to research how to do a multiple Python / Django deployment using Apache VirtualHosts.

The issue I am encountering seems straight forward,

ImportError: Could not import settings 'hub.settings' (Is it on sys.path?): No module named hub.settings, referer: proposals.internal.local

The trouble I am having is that proposals.internal.local is using proposals.settings and the hub.settings is actually from hub.internal.local.

If I run just proposal or hub on their own, I do not encounter the above mentioned problem, however, when I do run them both - as people use them. The sys.path seems to be updated for both of the projects.

[APACHE CONFIGS - HUB]

<VirtualHost *:80>

    ServerName hub.internal.local

    DocumentRoot /var/www/hub.internal.local/hub/hub/static
    Alias /static/  /var/www/hub.internal.local/hub/hub/static/

    <Directory /var/www/hub.internal.local/hub/hub/static>

        Allow from all

    </Directory>

    WSGIScriptAlias / /var/www/hub.internal.local/hub/hub/wsgi.py

</VirtualHost>

[APACHE CONFIGS - PROPOSALS]

<VirtualHost *:80>

    ServerName proposals.internal.local

    DocumentRoot /var/www/proposals.internal.local/proposal/proposal/static
    Alias /static/  /var/www/proposals.internal.local/proposal/proposal/static/

    <Directory /var/www/proposals.internal.local/proposal/proposal/static>

        Allow from all

    </Directory>

    WSGIScriptAlias / /var/www/proposals.internal.local/proposal/proposal/wsgi.py

</VirtualHost>

[wsgi.py - HUB]

import os
import sys

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hub.settings")
sys.path.append('/var/www/hub.internal.local')
sys.path.append('/var/www/hub.internal.local/hub')

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

[wsgi.py - PROPOSALS]

import os
import sys

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proposal.settings")
sys.path.append('/var/www/proposals.internal.local')
sys.path.append('/var/www/proposals.internal.local/proposal')

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Clearly I am missing something but I am not seeing anything unusual from the documentation.


Solution 1:

Do not use os.environ.setdefault(). Django screwed up the hosting of multiple applications in one mod_wsgi process when they switched to that way of setting environment variables.

This is documented in my blog: Requests running in wrong Django instance under Apache/mod_wsgi.

There are two solutions if this is the cause. The quickest is to replace the use of setdefault() to set the environment variable in the WSGI script file with more usual assignment.

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

An alternative which involves a bit more work, but can have other benefits, is to switch to using daemon mode of mod_wsgi to run the Django instances and delegate each to a separate set of processes. By running the Django instances in separate processes there can be no possibility of environment variables leaking from one to the other.

WSGIDaemonProcess project-2
WSGIScriptAlias /suburl /some/path/project-2/wsgi.py process-group=project-2

WSGIDaemonProcess project-1
WSGIScriptAlias / /some/path/project-1/wsgi.py process-group=project-1