Skip to content

Commit

Permalink
compatibility with django 1.4 and more related fixes.
Browse files Browse the repository at this point in the history
- handle new way to launch applications in django 1.4
- simplify the way we discover the project path and settings
- add --pythonpath & --settings options for django applications
- still compatible with older versions (>=1.1)
-handle DJANGO_SETTINGS_MODULE env.

close #283, #275, #274, #241
  • Loading branch information
benoitc committed Feb 19, 2012
1 parent a3aa143 commit cc43f89
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 269 deletions.
4 changes: 2 additions & 2 deletions examples/frameworks/djangotest/settings.py
Expand Up @@ -14,8 +14,8 @@

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test.db',
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test.db',
}
}

Expand Down
112 changes: 112 additions & 0 deletions gunicorn/app/django_wsgi.py
@@ -0,0 +1,112 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.

""" module used to build the django wsgi application """

import logging
import os
import re
import sys
import time
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

from django.conf import settings
from django.core.management.base import CommandError
from django.core.management.validation import get_validation_errors
from django.utils import translation
from django.core.servers.basehttp import AdminMediaHandler, WSGIServerException
try:
from django.core.servers.basehttp import get_internal_wsgi_application
django14 = True
except ImportError:
from django.core.handlers.wsgi import WSGIHandler
django14 = False

from gunicorn import util

def make_wsgi_application():
# validate models
s = StringIO()
if get_validation_errors(s):
s.seek(0)
error = s.read()
sys.stderr.write("One or more models did not validate:\n%s" % error)
sys.stderr.flush()

sys.exit(1)

translation.activate(settings.LANGUAGE_CODE)
if django14:
return get_internal_wsgi_application()
return WSGIHandler()

def reload_django_settings():
mod = util.import_module(os.environ['DJANGO_SETTINGS_MODULE'])

# reload module
reload(mod)

# reload settings.
# USe code from django.settings.Settings module.

# Settings that should be converted into tuples if they're mistakenly entered
# as strings.
tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS")

for setting in dir(mod):
if setting == setting.upper():
setting_value = getattr(mod, setting)
if setting in tuple_settings and type(setting_value) == str:
setting_value = (setting_value,) # In case the user forgot the comma.
setattr(settings, setting, setting_value)

# Expand entries in INSTALLED_APPS like "django.contrib.*" to a list
# of all those apps.
new_installed_apps = []
for app in settings.INSTALLED_APPS:
if app.endswith('.*'):
app_mod = util.import_module(app[:-2])
appdir = os.path.dirname(app_mod.__file__)
app_subdirs = os.listdir(appdir)
app_subdirs.sort()
name_pattern = re.compile(r'[a-zA-Z]\w*')
for d in app_subdirs:
if name_pattern.match(d) and os.path.isdir(os.path.join(appdir, d)):
new_installed_apps.append('%s.%s' % (app[:-2], d))
else:
new_installed_apps.append(app)
setattr(settings, "INSTALLED_APPS", new_installed_apps)

if hasattr(time, 'tzset') and settings.TIME_ZONE:
# When we can, attempt to validate the timezone. If we can't find
# this file, no check happens and it's harmless.
zoneinfo_root = '/usr/share/zoneinfo'
if (os.path.exists(zoneinfo_root) and not
os.path.exists(os.path.join(zoneinfo_root,
*(settings.TIME_ZONE.split('/'))))):
raise ValueError("Incorrect timezone setting: %s" %
settings.TIME_ZONE)
# Move the time zone info into os.environ. See ticket #2315 for why
# we don't do this unconditionally (breaks Windows).
os.environ['TZ'] = settings.TIME_ZONE
time.tzset()

# Settings are configured, so we can set up the logger if required
if getattr(settings, 'LOGGING_CONFIG', False):
# First find the logging configuration function ...
logging_config_path, logging_config_func_name = settings.LOGGING_CONFIG.rsplit('.', 1)
logging_config_module = util.import_module(logging_config_path)
logging_config_func = getattr(logging_config_module, logging_config_func_name)

# ... then invoke it with the logging settings
logging_config_func(settings.LOGGING)


def make_command_wsgi_application(admin_mediapath):
reload_django_settings()
return AdminMediaHandler(make_wsgi_application(), admin_mediapath)

0 comments on commit cc43f89

Please sign in to comment.