how to debug basic issues configuring django to be served with apache and mod-wsgi?

  • Last Update :
  • Techknowledgy :

You could try adding this to your

path = os.path.join(os.path.dirname(__file__), "..") # Adapt the path here to match the root of your django project
if path not in sys.path:

Maybe it's a permission problem. In your WSGIDaemonProcess you don't specify any user or group, and maybe apache is not allowed to read/execute the files. Can you try adding user and group to this line like this:

    WSGIDaemonProcess user=<username> group=<username> python-path=/home/cmc/src/cm_central:/home/cmc/virtualenvs/cmc/lib/python2.7/site-packages

Also, you're not using a DocumentRoot. Maybe that's why it's not finding the right path? In my vhosts, I always include a DocumentRoot, which has the same path as the Directory but with a leading slash, in your case:

<VirtualHost *:80>
   DocumentRoot /home/cmc/src/cm_central/cm_central/

The error message is pretty explicit already -- mod_wsgi cannot find your settings file (line 2, os.environ.setdefault), check your system path (I understand that Django can find your settings file when you use runserver, but mod_wsgi cannot). To check your system path, you can modify the file and print / log the sys.path at the very top of the file:

import sys
print sys.path

In addition to the virtual env docs pointed to by @Thomas Waldmann, you may also need to manually append the project directory into the sys.path, as mentioned here in the Django config docs. Example code I use is below:

ALLDIRS = ['/usr/local/pythonenv/assessments/lib/python2.6/site-packages']

import os
import sys
import site

# from https: //

   sys.path.insert(0, '/var/www/assessments/assessments-main/') # file here
sys.path.insert(1, '/var/www/assessments/')

prev_sys_path = list(sys.path)
for directory in ALLDIRS:

new_sys_path = []
for item in list(sys.path):
   if item not in prev_sys_path:

sys.path[: 0] = new_sys_path

os.environ['DJANGO_SETTINGS_MODULE'] = 'assessments-main.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

import sys, os

print "__name__ =", __name__
print "__file__ =", __file__
print "os.getpid() =", os.getpid()
print "os.getcwd() =", os.getcwd()
print "os.curdir =", os.curdir
print "sys.path =", repr(sys.path)
print "sys.modules.keys() =", repr(sys.modules.keys())
print "sys.modules.has_key('mysite') =", sys.modules.has_key('mysite')
if sys.modules.has_key('mysite'):
   print "sys.modules['mysite'].__name__ =", sys.modules['mysite'].__name__
print "sys.modules['mysite'].__file__ =", sys.modules['mysite'].__file__
print "os.environ['DJANGO_SETTINGS_MODULE'] =", os.environ.get('DJANGO_SETTINGS_MODULE', None)

Suggestion : 2

Do note though that one cannot be using the ability of mod_wsgi to run your application in a daemon process when doing this. The WSGI application must be running within the main Apache process.,To use the error catching middleware from Paste you simply need to wrap your existing application with it such that it then becomes the top level application entry point:,The directives must be placed at global scope within the main Apache configuration files and will affect the whole Apache web server.,If using Apache 2.X on a UNIX system, a better approach is to use daemon mode of mod_wsgi and delegate your application to run in a single daemon process. This process may be single or multithreaded as per any threading requirements of your application.

LogLevel info
def application(environ, start_response):
   status = '200 OK'
output = b 'Hello World!'

print("application debug #1", file = environ['wsgi.errors']))

response_headers = [('Content-type', 'text/plain'),
   ('Content-Length', str(len(output)))
start_response(status, response_headers)

print("application debug #2", file = environ['wsgi.errors']))

return [output]
from __future__
import print_function
print >> environ['wsgi.errors']), "application debug #N"
import sys

print("application debug #3", file = sys.stderr)
IOError: sys.stdout access restricted by mod_wsgi

Suggestion : 3

The first bit in the WSGIScriptAlias line is the base URL path you want to serve your application at (/ indicates the root url), and the second is the location of a “WSGI file” – see below – on your system, usually inside of your project package (mysite in this example). This tells Apache to serve any request below the given URL using the WSGI application defined in that file.,If you want to serve your project in a subdirectory ( in this example), you can add WSGIScriptAlias to the configuration above:,If, however, you have no option but to serve media files on the same Apache VirtualHost as Django, you can set up Apache to serve some URLs as static media, and others using the mod_wsgi interface to Django.,Use an Alias directive, as demonstrated above, to alias the appropriate URL (probably STATIC_URL + admin/) to the actual location of the admin files.

WSGIScriptAlias / /path/to/
WSGIPythonHome /path/to/venv
WSGIPythonPath /path/to/

<Directory /path/to/>
      Require all granted
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
os.environ["DJANGO_SETTINGS_MODULE"] = "{{ project_name }}.settings"
export LANG = 'en_US.UTF-8'
export LC_ALL = 'en_US.UTF-8'
WSGIDaemonProcess lang = 'en_US.UTF-8'
locale = 'en_US.UTF-8'
WSGIDaemonProcess python - home = /path/to / venv python - path = /path/to /

Suggestion : 4

How to debug basic issues configuring django to be served with apache and mod-wsgi?,How to debug django staticfiles served with whitenoise, gunicorn, and heroku?,How to debug django with logging on Apache?,How to configure Apache alias settings to let django debug toolbar work properly?

   'version': 1,
   'disable_existing_loggers': True,
   'formatters': {
      'standard': {
         'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
         'datefmt': "%d/%b/%Y %H:%M:%S"
   'handlers': {
      'null': {
         'level': 'DEBUG',
         'class': 'django.utils.log.NullHandler',
      'logfile': {
         'level': 'DEBUG',
         'class': 'logging.handlers.RotatingFileHandler',
         'filename': BASE_DIR + "/logfile",
         'maxBytes': 50000,
         'backupCount': 2,
         'formatter': 'standard',
      'console': {
         'level': 'INFO',
         'class': 'logging.StreamHandler',
         'formatter': 'standard'
   'loggers': {
      'django': {
         'handlers': ['console'],
         'propagate': True,
         'level': 'WARN',
      'django.db.backends': {
         'handlers': ['console'],
         'level': 'DEBUG',
         'propagate': False,
      '': {
         'handlers': ['console', 'logfile'],
         'level': 'DEBUG',

import logging
try: # Python 2.7 +
   from logging
import NullHandler
except ImportError:
   class NullHandler(logging.Handler):
   def emit(self, record):

log = logging.getLogger(__name__)

def demo(foo):
   if foo not bar: