1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

Fixed #16360 -- Added WSGI entrypoint to startproject layout, and enabled internal servers (runserver and runfcgi) to use an externally-defined WSGI application. Thanks to Armin Ronacher, Jannis Leidel, Alex Gaynor, ptone, and Jacob Kaplan-Moss.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17022 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Carl Meyer
2011-10-22 04:30:10 +00:00
parent dca81ad58a
commit 145a77edc9
34 changed files with 635 additions and 208 deletions

View File

@@ -242,8 +242,8 @@ def get_script_name(environ):
Returns the equivalent of the HTTP request's SCRIPT_NAME environment
variable. If Apache mod_rewrite has been used, returns what would have been
the script name prior to any rewriting (so it's the script name as seen
from the client's perspective), unless FORCE_SCRIPT_NAME is set (to
anything).
from the client's perspective), unless the FORCE_SCRIPT_NAME setting is
set (to anything).
"""
from django.conf import settings
if settings.FORCE_SCRIPT_NAME is not None:

View File

@@ -124,6 +124,7 @@ class LimitedStream(object):
self.buffer = sio.read()
return line
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = base.get_script_name(environ)
@@ -202,13 +203,12 @@ class WSGIRequest(http.HttpRequest):
FILES = property(_get_files)
REQUEST = property(_get_request)
class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest
def __call__(self, environ, start_response):
from django.conf import settings
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
if self._request_middleware is None:
@@ -253,4 +253,3 @@ class WSGIHandler(base.BaseHandler):
response_headers.append(('Set-Cookie', str(c.output(header=''))))
start_response(status, response_headers)
return response

View File

@@ -5,8 +5,7 @@ import sys
import socket
from django.core.management.base import BaseCommand, CommandError
from django.core.handlers.wsgi import WSGIHandler
from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException
from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException, get_internal_wsgi_application
from django.utils import autoreload
naiveip_re = re.compile(r"""^(?:
@@ -37,7 +36,7 @@ class BaseRunserverCommand(BaseCommand):
"""
Returns the default WSGI handler for the runner.
"""
return WSGIHandler()
return get_internal_wsgi_application()
def handle(self, addrport='', *args, **options):
self.use_ipv6 = options.get('use_ipv6')

View File

@@ -18,7 +18,10 @@ from wsgiref import simple_server
from wsgiref.util import FileWrapper # for backwards compatibility
import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style
from django.core.wsgi import get_wsgi_application
from django.utils.importlib import import_module
from django.utils._os import safe_join
from django.views import static
@@ -27,6 +30,43 @@ from django.contrib.staticfiles import handlers
__all__ = ['WSGIServer', 'WSGIRequestHandler']
def get_internal_wsgi_application():
"""
Loads and returns the WSGI application as configured by the user in
``settings.WSGI_APPLICATION``. With the default ``startproject`` layout,
this will be the ``application`` object in ``projectname/wsgi.py``.
This function, and the ``WSGI_APPLICATION`` setting itself, are only useful
for Django's internal servers (runserver, runfcgi); external WSGI servers
should just be configured to point to the correct application object
directly.
If settings.WSGI_APPLICATION is not set (is ``None``), we just return
whatever ``django.core.wsgi.get_wsgi_application`` returns.
"""
from django.conf import settings
app_path = getattr(settings, 'WSGI_APPLICATION')
if app_path is None:
return get_wsgi_application()
module_name, attr = app_path.rsplit('.', 1)
try:
mod = import_module(module_name)
except ImportError, e:
raise ImproperlyConfigured(
"WSGI application '%s' could not be loaded; "
"could not import module '%s': %s" % (app_path, module_name, e))
try:
app = getattr(mod, attr)
except AttributeError, e:
raise ImproperlyConfigured(
"WSGI application '%s' could not be loaded; "
"can't find '%s' in module '%s': %s"
% (app_path, attr, module_name, e))
return app
class WSGIServerException(Exception):
pass

View File

@@ -139,7 +139,7 @@ def runfastcgi(argset=[], **kwargs):
return False
# Prep up and go
from django.core.handlers.wsgi import WSGIHandler
from django.core.servers.basehttp import get_internal_wsgi_application
if options["host"] and options["port"] and not options["socket"]:
wsgi_opts['bindAddress'] = (options["host"], int(options["port"]))
@@ -178,7 +178,7 @@ def runfastcgi(argset=[], **kwargs):
fp.write("%d\n" % os.getpid())
fp.close()
WSGIServer(WSGIHandler(), **wsgi_opts).run()
WSGIServer(get_internal_wsgi_application(), **wsgi_opts).run()
if __name__ == '__main__':
runfastcgi(sys.argv[1:])

13
django/core/wsgi.py Normal file
View File

@@ -0,0 +1,13 @@
from django.core.handlers.wsgi import WSGIHandler
def get_wsgi_application():
"""
The public interface to Django's WSGI support. Should return a WSGI
callable.
Allows us to avoid making django.core.handlers.WSGIHandler public API, in
case the internal WSGI implementation changes or moves in the future.
"""
return WSGIHandler()