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:
parent
dca81ad58a
commit
145a77edc9
|
@ -407,6 +407,13 @@ X_FRAME_OPTIONS = 'SAMEORIGIN'
|
||||||
|
|
||||||
USE_X_FORWARDED_HOST = False
|
USE_X_FORWARDED_HOST = False
|
||||||
|
|
||||||
|
# The Python dotted path to the WSGI application that Django's internal servers
|
||||||
|
# (runserver, runfcgi) will use. If `None`, the return value of
|
||||||
|
# 'django.core.wsgi.get_wsgi_application' is used, thus preserving the same
|
||||||
|
# behavior as previous versions of Django. Otherwise this should point to an
|
||||||
|
# actual WSGI application object.
|
||||||
|
WSGI_APPLICATION = None
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# MIDDLEWARE #
|
# MIDDLEWARE #
|
||||||
##############
|
##############
|
||||||
|
|
|
@ -99,6 +99,9 @@ MIDDLEWARE_CLASSES = (
|
||||||
|
|
||||||
ROOT_URLCONF = '{{ project_name }}.urls'
|
ROOT_URLCONF = '{{ project_name }}.urls'
|
||||||
|
|
||||||
|
# Python dotted path to the WSGI application used by Django's runserver.
|
||||||
|
WSGI_APPLICATION = '{{ project_name }}.wsgi.application'
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||||
# Always use forward slashes, even on Windows.
|
# Always use forward slashes, even on Windows.
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""
|
||||||
|
WSGI config for {{ project_name }} project.
|
||||||
|
|
||||||
|
This module contains the WSGI application used by Django's development server
|
||||||
|
and any production WSGI deployments. It should expose a module-level variable
|
||||||
|
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
||||||
|
this application via the ``WSGI_APPLICATION`` setting.
|
||||||
|
|
||||||
|
Usually you will have the standard Django WSGI application here, but it also
|
||||||
|
might make sense to replace the whole Django WSGI application with a custom one
|
||||||
|
that later delegates to the Django one. For example, you could introduce WSGI
|
||||||
|
middleware here, or combine a Django application with an application of another
|
||||||
|
framework.
|
||||||
|
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
|
||||||
|
|
||||||
|
# This application object is used by any WSGI server configured to use this
|
||||||
|
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||||
|
# setting points here.
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
application = get_wsgi_application()
|
||||||
|
|
||||||
|
# Apply WSGI middleware here.
|
||||||
|
# from helloworld.wsgi import HelloWorldApplication
|
||||||
|
# application = HelloWorldApplication(application)
|
|
@ -16,12 +16,14 @@ class Command(BaseRunserverCommand):
|
||||||
|
|
||||||
def get_handler(self, *args, **options):
|
def get_handler(self, *args, **options):
|
||||||
"""
|
"""
|
||||||
Returns the static files serving handler.
|
Returns the static files serving handler wrapping the default handler,
|
||||||
|
if static files should be served. Otherwise just returns the default
|
||||||
|
handler.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
handler = super(Command, self).get_handler(*args, **options)
|
handler = super(Command, self).get_handler(*args, **options)
|
||||||
use_static_handler = options.get('use_static_handler', True)
|
use_static_handler = options.get('use_static_handler', True)
|
||||||
insecure_serving = options.get('insecure_serving', False)
|
insecure_serving = options.get('insecure_serving', False)
|
||||||
if (settings.DEBUG and use_static_handler or
|
if use_static_handler and (settings.DEBUG or insecure_serving):
|
||||||
(use_static_handler and insecure_serving)):
|
return StaticFilesHandler(handler)
|
||||||
handler = StaticFilesHandler(handler)
|
|
||||||
return handler
|
return handler
|
||||||
|
|
|
@ -242,8 +242,8 @@ def get_script_name(environ):
|
||||||
Returns the equivalent of the HTTP request's SCRIPT_NAME environment
|
Returns the equivalent of the HTTP request's SCRIPT_NAME environment
|
||||||
variable. If Apache mod_rewrite has been used, returns what would have been
|
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
|
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
|
from the client's perspective), unless the FORCE_SCRIPT_NAME setting is
|
||||||
anything).
|
set (to anything).
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
if settings.FORCE_SCRIPT_NAME is not None:
|
if settings.FORCE_SCRIPT_NAME is not None:
|
||||||
|
|
|
@ -124,6 +124,7 @@ class LimitedStream(object):
|
||||||
self.buffer = sio.read()
|
self.buffer = sio.read()
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
class WSGIRequest(http.HttpRequest):
|
class WSGIRequest(http.HttpRequest):
|
||||||
def __init__(self, environ):
|
def __init__(self, environ):
|
||||||
script_name = base.get_script_name(environ)
|
script_name = base.get_script_name(environ)
|
||||||
|
@ -202,13 +203,12 @@ class WSGIRequest(http.HttpRequest):
|
||||||
FILES = property(_get_files)
|
FILES = property(_get_files)
|
||||||
REQUEST = property(_get_request)
|
REQUEST = property(_get_request)
|
||||||
|
|
||||||
|
|
||||||
class WSGIHandler(base.BaseHandler):
|
class WSGIHandler(base.BaseHandler):
|
||||||
initLock = Lock()
|
initLock = Lock()
|
||||||
request_class = WSGIRequest
|
request_class = WSGIRequest
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
# Set up middleware if needed. We couldn't do this earlier, because
|
# Set up middleware if needed. We couldn't do this earlier, because
|
||||||
# settings weren't available.
|
# settings weren't available.
|
||||||
if self._request_middleware is None:
|
if self._request_middleware is None:
|
||||||
|
@ -253,4 +253,3 @@ class WSGIHandler(base.BaseHandler):
|
||||||
response_headers.append(('Set-Cookie', str(c.output(header=''))))
|
response_headers.append(('Set-Cookie', str(c.output(header=''))))
|
||||||
start_response(status, response_headers)
|
start_response(status, response_headers)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,7 @@ import sys
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException, get_internal_wsgi_application
|
||||||
from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException
|
|
||||||
from django.utils import autoreload
|
from django.utils import autoreload
|
||||||
|
|
||||||
naiveip_re = re.compile(r"""^(?:
|
naiveip_re = re.compile(r"""^(?:
|
||||||
|
@ -37,7 +36,7 @@ class BaseRunserverCommand(BaseCommand):
|
||||||
"""
|
"""
|
||||||
Returns the default WSGI handler for the runner.
|
Returns the default WSGI handler for the runner.
|
||||||
"""
|
"""
|
||||||
return WSGIHandler()
|
return get_internal_wsgi_application()
|
||||||
|
|
||||||
def handle(self, addrport='', *args, **options):
|
def handle(self, addrport='', *args, **options):
|
||||||
self.use_ipv6 = options.get('use_ipv6')
|
self.use_ipv6 = options.get('use_ipv6')
|
||||||
|
|
|
@ -18,7 +18,10 @@ from wsgiref import simple_server
|
||||||
from wsgiref.util import FileWrapper # for backwards compatibility
|
from wsgiref.util import FileWrapper # for backwards compatibility
|
||||||
|
|
||||||
import django
|
import django
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.management.color import color_style
|
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.utils._os import safe_join
|
||||||
from django.views import static
|
from django.views import static
|
||||||
|
|
||||||
|
@ -27,6 +30,43 @@ from django.contrib.staticfiles import handlers
|
||||||
__all__ = ['WSGIServer', 'WSGIRequestHandler']
|
__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):
|
class WSGIServerException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ def runfastcgi(argset=[], **kwargs):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Prep up and go
|
# 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"]:
|
if options["host"] and options["port"] and not options["socket"]:
|
||||||
wsgi_opts['bindAddress'] = (options["host"], int(options["port"]))
|
wsgi_opts['bindAddress'] = (options["host"], int(options["port"]))
|
||||||
|
@ -178,7 +178,7 @@ def runfastcgi(argset=[], **kwargs):
|
||||||
fp.write("%d\n" % os.getpid())
|
fp.write("%d\n" % os.getpid())
|
||||||
fp.close()
|
fp.close()
|
||||||
|
|
||||||
WSGIServer(WSGIHandler(), **wsgi_opts).run()
|
WSGIServer(get_internal_wsgi_application(), **wsgi_opts).run()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
runfastcgi(sys.argv[1:])
|
runfastcgi(sys.argv[1:])
|
||||||
|
|
|
@ -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()
|
|
@ -23,7 +23,7 @@ usage.
|
||||||
For a development environment -- if you just want to experiment with Django --
|
For a development environment -- if you just want to experiment with Django --
|
||||||
you don't need to have a separate Web server installed; Django comes with its
|
you don't need to have a separate Web server installed; Django comes with its
|
||||||
own lightweight development server. For a production environment, Django follows
|
own lightweight development server. For a production environment, Django follows
|
||||||
the WSGI spec, :pep:`333`, which means it can run on a variety of server
|
the WSGI spec, :pep:`3333`, which means it can run on a variety of server
|
||||||
platforms. See :doc:`Deploying Django </howto/deployment/index>` for some
|
platforms. See :doc:`Deploying Django </howto/deployment/index>` for some
|
||||||
popular alternatives. Also, the `server arrangements wiki page`_ contains
|
popular alternatives. Also, the `server arrangements wiki page`_ contains
|
||||||
details for several deployment strategies.
|
details for several deployment strategies.
|
||||||
|
|
|
@ -4,10 +4,9 @@ How to use Django with FastCGI, SCGI, or AJP
|
||||||
|
|
||||||
.. highlight:: bash
|
.. highlight:: bash
|
||||||
|
|
||||||
Although the current preferred setup for running Django is :doc:`Apache with
|
Although :doc:`WSGI</howto/deployment/wsgi/index>` is the preferred deployment
|
||||||
mod_wsgi </howto/deployment/modwsgi>`, many people use shared hosting, on
|
platform for Django, many people use shared hosting, on which protocols such as
|
||||||
which protocols such as FastCGI, SCGI or AJP are the only viable options. In
|
FastCGI, SCGI or AJP are the only viable options.
|
||||||
some setups, these protocols may provide better performance than mod_wsgi_.
|
|
||||||
|
|
||||||
.. admonition:: Note
|
.. admonition:: Note
|
||||||
|
|
||||||
|
@ -20,13 +19,13 @@ serve pages to a Web server. The Web server delegates the incoming Web requests
|
||||||
(via a socket) to FastCGI, which executes the code and passes the response back
|
(via a socket) to FastCGI, which executes the code and passes the response back
|
||||||
to the Web server, which, in turn, passes it back to the client's Web browser.
|
to the Web server, which, in turn, passes it back to the client's Web browser.
|
||||||
|
|
||||||
Like mod_wsgi, FastCGI allows code to stay in memory, allowing requests to be
|
Like WSGI, FastCGI allows code to stay in memory, allowing requests to be
|
||||||
served with no startup time. While mod_wsgi can either be configured embedded
|
served with no startup time. While
|
||||||
in the Apache Web server process or as a separate daemon process, a FastCGI
|
e.g. :doc:`mod_wsgi</howto/deployment/wsgi/modwsgi>` can either be configured
|
||||||
process never runs inside the Web server process, always in a separate,
|
embedded in the Apache Web server process or as a separate daemon process, a
|
||||||
|
FastCGI process never runs inside the Web server process, always in a separate,
|
||||||
persistent process.
|
persistent process.
|
||||||
|
|
||||||
.. _mod_wsgi: http://code.google.com/p/modwsgi/
|
|
||||||
.. _mod_perl: http://perl.apache.org/
|
.. _mod_perl: http://perl.apache.org/
|
||||||
|
|
||||||
.. admonition:: Why run code in a separate process?
|
.. admonition:: Why run code in a separate process?
|
||||||
|
|
|
@ -9,13 +9,12 @@ ways to easily deploy Django:
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
modwsgi
|
wsgi/index
|
||||||
uwsgi
|
|
||||||
fastcgi
|
fastcgi
|
||||||
mod_python (deprecated) <modpython>
|
mod_python (deprecated) <modpython>
|
||||||
|
|
||||||
If you're new to deploying Django and/or Python, we'd recommend you try
|
If you're new to deploying Django and/or Python, we'd recommend you try
|
||||||
:doc:`mod_wsgi </howto/deployment/modwsgi>` first. In most cases it'll be
|
:doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` first. In most cases it'll be
|
||||||
the easiest, fastest, and most stable deployment choice.
|
the easiest, fastest, and most stable deployment choice.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
|
@ -7,14 +7,14 @@ How to use Django with Apache and mod_python
|
||||||
Support for mod_python has been deprecated, and will be removed in
|
Support for mod_python has been deprecated, and will be removed in
|
||||||
Django 1.5. If you are configuring a new deployment, you are
|
Django 1.5. If you are configuring a new deployment, you are
|
||||||
strongly encouraged to consider using :doc:`mod_wsgi
|
strongly encouraged to consider using :doc:`mod_wsgi
|
||||||
</howto/deployment/modwsgi>` or any of the other :doc:`supported
|
</howto/deployment/wsgi/modwsgi>` or any of the other :doc:`supported
|
||||||
backends </howto/deployment/index>`.
|
servers </howto/deployment/index>`.
|
||||||
|
|
||||||
.. highlight:: apache
|
.. highlight:: apache
|
||||||
|
|
||||||
The `mod_python`_ module for Apache_ can be used to deploy Django to a
|
The `mod_python`_ module for Apache_ can be used to deploy Django to a
|
||||||
production server, although it has been mostly superseded by the simpler
|
production server, although it has been mostly superseded by the simpler
|
||||||
:doc:`mod_wsgi deployment option </howto/deployment/modwsgi>`.
|
:doc:`mod_wsgi deployment option </howto/deployment/wsgi/modwsgi>`.
|
||||||
|
|
||||||
mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
|
mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
|
||||||
Apache and loads Python code into memory when the server starts. Code stays in
|
Apache and loads Python code into memory when the server starts. Code stays in
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
==========================================
|
|
||||||
How to use Django with Apache and mod_wsgi
|
|
||||||
==========================================
|
|
||||||
|
|
||||||
Deploying Django with Apache_ and `mod_wsgi`_ is the recommended way to get
|
|
||||||
Django into production.
|
|
||||||
|
|
||||||
.. _Apache: http://httpd.apache.org/
|
|
||||||
.. _mod_wsgi: http://code.google.com/p/modwsgi/
|
|
||||||
|
|
||||||
mod_wsgi is an Apache module which can be used to host any Python application
|
|
||||||
which supports the Python WSGI interface described in :pep:`3333`, including
|
|
||||||
Django. Django will work with any version of Apache which supports mod_wsgi.
|
|
||||||
|
|
||||||
The `official mod_wsgi documentation`_ is fantastic; it's your source for all
|
|
||||||
the details about how to use mod_wsgi. You'll probably want to start with the
|
|
||||||
`installation and configuration documentation`_.
|
|
||||||
|
|
||||||
.. _official mod_wsgi documentation: http://code.google.com/p/modwsgi/
|
|
||||||
.. _installation and configuration documentation: http://code.google.com/p/modwsgi/wiki/InstallationInstructions
|
|
||||||
|
|
||||||
Basic configuration
|
|
||||||
===================
|
|
||||||
|
|
||||||
Once you've got mod_wsgi installed and activated, edit your ``httpd.conf`` file
|
|
||||||
and add::
|
|
||||||
|
|
||||||
WSGIScriptAlias / /path/to/mysite/apache/django.wsgi
|
|
||||||
|
|
||||||
The first bit above is the url you want to be serving 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. This tells Apache
|
|
||||||
to serve any request below the given URL using the WSGI application defined by that file.
|
|
||||||
|
|
||||||
Next we'll need to actually create this WSGI application, so create the file
|
|
||||||
mentioned in the second part of ``WSGIScriptAlias`` and add::
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
|
|
||||||
|
|
||||||
import django.core.handlers.wsgi
|
|
||||||
application = django.core.handlers.wsgi.WSGIHandler()
|
|
||||||
|
|
||||||
If your project is not on your ``PYTHONPATH`` by default you can add::
|
|
||||||
|
|
||||||
path = '/path/to/mysite'
|
|
||||||
if path not in sys.path:
|
|
||||||
sys.path.append(path)
|
|
||||||
|
|
||||||
just below the ``import sys`` line to place your project on the path. Remember to
|
|
||||||
replace 'mysite.settings' with your correct settings file, and '/path/to/mysite'
|
|
||||||
with your own project's location.
|
|
||||||
|
|
||||||
.. _serving-files:
|
|
||||||
|
|
||||||
Serving files
|
|
||||||
=============
|
|
||||||
|
|
||||||
Django doesn't serve files itself; it leaves that job to whichever Web
|
|
||||||
server you choose.
|
|
||||||
|
|
||||||
We recommend using a separate Web server -- i.e., one that's not also running
|
|
||||||
Django -- for serving media. Here are some good choices:
|
|
||||||
|
|
||||||
* lighttpd_
|
|
||||||
* Nginx_
|
|
||||||
* TUX_
|
|
||||||
* A stripped-down version of Apache_
|
|
||||||
* Cherokee_
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
This example sets up Django at the site root, but explicitly serves
|
|
||||||
``robots.txt``, ``favicon.ico``, any CSS file, and anything in the
|
|
||||||
``/static/`` and ``/media/`` URL space as a static file. All other URLs
|
|
||||||
will be served using mod_wsgi::
|
|
||||||
|
|
||||||
Alias /robots.txt /usr/local/wsgi/static/robots.txt
|
|
||||||
Alias /favicon.ico /usr/local/wsgi/static/favicon.ico
|
|
||||||
|
|
||||||
AliasMatch ^/([^/]*\.css) /usr/local/wsgi/static/styles/$1
|
|
||||||
|
|
||||||
Alias /media/ /usr/local/wsgi/media/
|
|
||||||
Alias /static/ /usr/local/wsgi/static/
|
|
||||||
|
|
||||||
<Directory /usr/local/wsgi/static>
|
|
||||||
Order deny,allow
|
|
||||||
Allow from all
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
<Directory /usr/local/wsgi/media>
|
|
||||||
Order deny,allow
|
|
||||||
Allow from all
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi
|
|
||||||
|
|
||||||
<Directory /usr/local/wsgi/scripts>
|
|
||||||
Order allow,deny
|
|
||||||
Allow from all
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
.. _lighttpd: http://www.lighttpd.net/
|
|
||||||
.. _Nginx: http://wiki.nginx.org/Main
|
|
||||||
.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
|
|
||||||
.. _Apache: http://httpd.apache.org/
|
|
||||||
.. _Cherokee: http://www.cherokee-project.com/
|
|
||||||
|
|
||||||
.. More details on configuring a mod_wsgi site to serve static files can be found
|
|
||||||
.. in the mod_wsgi documentation on `hosting static files`_.
|
|
||||||
|
|
||||||
.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files
|
|
||||||
|
|
||||||
.. _serving-the-admin-files:
|
|
||||||
|
|
||||||
Serving the admin files
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Note that the Django development server automagically serves the static files
|
|
||||||
of the admin app, but this is not the case when you use any other server
|
|
||||||
arrangement. You're responsible for setting up Apache, or whichever media
|
|
||||||
server you're using, to serve the admin files.
|
|
||||||
|
|
||||||
The admin files live in (:file:`django/contrib/admin/static/admin`) of the
|
|
||||||
Django distribution.
|
|
||||||
|
|
||||||
We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
|
|
||||||
the admin files, but here are two other approaches:
|
|
||||||
|
|
||||||
1. Create a symbolic link to the admin static files from within your
|
|
||||||
document root.
|
|
||||||
|
|
||||||
2. Or, copy the admin static files so that they live within your Apache
|
|
||||||
document root.
|
|
||||||
|
|
||||||
Details
|
|
||||||
=======
|
|
||||||
|
|
||||||
For more details, see the `mod_wsgi documentation on Django integration`_,
|
|
||||||
which explains the above in more detail, and walks through all the various
|
|
||||||
options you've got when deploying under mod_wsgi.
|
|
||||||
|
|
||||||
.. _mod_wsgi documentation on Django integration: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
===============================
|
||||||
|
How to use Django with Gunicorn
|
||||||
|
===============================
|
||||||
|
|
||||||
|
.. highlight:: bash
|
||||||
|
|
||||||
|
Gunicorn_ ('Green Unicorn') is a pure-Python WSGI server for UNIX. It has no
|
||||||
|
dependencies and is easy to install and use.
|
||||||
|
|
||||||
|
.. _Gunicorn: http://gunicorn.org/
|
||||||
|
|
||||||
|
There are two ways to use Gunicorn with Django. One is to have Gunicorn treat
|
||||||
|
Django as just another WSGI application. The second is to use Gunicorn's
|
||||||
|
special `integration with Django`_.
|
||||||
|
|
||||||
|
.. _integration with Django: http://gunicorn.org/run.html#django-manage-py_
|
||||||
|
|
||||||
|
Installing Gunicorn
|
||||||
|
===================
|
||||||
|
|
||||||
|
Installing gunicorn is as easy as ``pip install gunicorn``. For more details,
|
||||||
|
see the `gunicorn documentation`_.
|
||||||
|
|
||||||
|
.. _gunicorn documentation: http://gunicorn.org/install.html
|
||||||
|
|
||||||
|
Running Django in Gunicorn as a generic WSGI application
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
When Gunicorn is installed, a ``gunicorn`` command is available which starts
|
||||||
|
the Gunicorn server process. At its simplest, gunicorn just needs to be called
|
||||||
|
with a the location of a WSGI application object.::
|
||||||
|
|
||||||
|
gunicorn [OPTIONS] APP_MODULE
|
||||||
|
|
||||||
|
Where ``APP_MODULE`` is of the pattern ``MODULE_NAME:VARIABLE_NAME``. The
|
||||||
|
module name should be a full dotted path. The variable name refers to a WSGI
|
||||||
|
callable that should be found in the specified module.
|
||||||
|
|
||||||
|
So for a typical Django project, invoking gunicorn would look like::
|
||||||
|
|
||||||
|
gunicorn myproject.wsgi:application
|
||||||
|
|
||||||
|
(This requires that your project be on the Python path; the simplest way to
|
||||||
|
ensure that is to run this command from the same directory as your
|
||||||
|
``manage.py`` file.)
|
||||||
|
|
||||||
|
|
||||||
|
Using Gunicorn's Django integration
|
||||||
|
===================================
|
||||||
|
|
||||||
|
To use Gunicorn's built-in Django integration, first add ``"gunicorn"`` to
|
||||||
|
:setting:`INSTALLED_APPS`. Then run ``python manage.py run_gunicorn``.
|
||||||
|
|
||||||
|
This provides a few Django-specific niceties:
|
||||||
|
|
||||||
|
* sets the gunicorn process name to be that of the project
|
||||||
|
|
||||||
|
* validates installed models
|
||||||
|
|
||||||
|
* allows an ``--adminmedia`` option for passing in the location of the
|
||||||
|
admin media files, mimicing the behavior of runserver.
|
||||||
|
|
||||||
|
See Gunicorn's `deployment documentation`_ for additional tips on starting and
|
||||||
|
maintaining the Gunicorn server.
|
||||||
|
|
||||||
|
.. _deployment documentation: http://gunicorn.org/deploy.html
|
|
@ -0,0 +1,72 @@
|
||||||
|
=======================
|
||||||
|
How to deploy with WSGI
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Django's primary deployment platform is WSGI_, the Python standard for web
|
||||||
|
servers and applications.
|
||||||
|
|
||||||
|
.. _WSGI: http://www.wsgi.org
|
||||||
|
|
||||||
|
Django's :djadmin:`startproject` management command sets up a simple default
|
||||||
|
WSGI configuration for you, which you can tweak as needed for your project, and
|
||||||
|
direct any WSGI-compliant webserver to use. Django includes getting-started
|
||||||
|
documentation for the following WSGI servers:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
modwsgi
|
||||||
|
gunicorn
|
||||||
|
uwsgi
|
||||||
|
|
||||||
|
The ``application`` object
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
One key concept of deploying with WSGI is to specify a central ``application``
|
||||||
|
callable object which the webserver uses to communicate with your code. This is
|
||||||
|
commonly specified as an object named ``application`` in a Python module
|
||||||
|
accessible to the server.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.4
|
||||||
|
|
||||||
|
The :djadmin:`startproject` command creates a :file:`projectname/wsgi.py` that
|
||||||
|
contains such an application callable.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Upgrading from a previous release of Django and don't have a :file:`wsgi.py`
|
||||||
|
file in your project? You can simply add one to your project's top-level
|
||||||
|
Python package (probably next to :file:`settings.py` and :file:`urls.py`)
|
||||||
|
with the contents below. If you want :djadmin:`runserver` to also make use
|
||||||
|
of this WSGI file, you can also add ``WSGI_APPLICATION =
|
||||||
|
"mysite.wsgi.application"`` in your settings (replacing ``mysite`` with the
|
||||||
|
name of your project).
|
||||||
|
|
||||||
|
Initially this file contains::
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
|
||||||
|
|
||||||
|
# This application object is used by the development server
|
||||||
|
# as well as any WSGI server configured to use this file.
|
||||||
|
from django.core.handlers.wsgi import get_wsgi_application
|
||||||
|
application = get_wsgi_application()
|
||||||
|
|
||||||
|
The ``os.environ.setdefault`` line just sets the default settings module to
|
||||||
|
use, if you haven't explicitly set the :envvar:`DJANGO_SETTINGS_MODULE`
|
||||||
|
environment variable. You'll need to edit this line to replace ``mysite`` with
|
||||||
|
the name of your project package, so the path to your settings module is
|
||||||
|
correct.
|
||||||
|
|
||||||
|
To apply `WSGI middleware`_ you can simply wrap the application object
|
||||||
|
in the same file::
|
||||||
|
|
||||||
|
from helloworld.wsgi import HelloWorldApplication
|
||||||
|
application = HelloWorldApplication(application)
|
||||||
|
|
||||||
|
You could also replace the Django WSGI application with a custom WSGI
|
||||||
|
application that later delegates to the Django WSGI application, if you want to
|
||||||
|
combine a Django application with a WSGI application of another framework.
|
||||||
|
|
||||||
|
.. _`WSGI middleware`: http://www.python.org/dev/peps/pep-3333/#middleware-components-that-play-both-sides
|
|
@ -0,0 +1,175 @@
|
||||||
|
==========================================
|
||||||
|
How to use Django with Apache and mod_wsgi
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
Deploying Django with Apache_ and `mod_wsgi`_ is a tried and tested way to get
|
||||||
|
Django into production.
|
||||||
|
|
||||||
|
.. _Apache: http://httpd.apache.org/
|
||||||
|
.. _mod_wsgi: http://code.google.com/p/modwsgi/
|
||||||
|
|
||||||
|
mod_wsgi is an Apache module which can host any Python WSGI_ application,
|
||||||
|
including Django. Django will work with any version of Apache which supports
|
||||||
|
mod_wsgi.
|
||||||
|
|
||||||
|
.. _WSGI: http://www.wsgi.org
|
||||||
|
|
||||||
|
The `official mod_wsgi documentation`_ is fantastic; it's your source for all
|
||||||
|
the details about how to use mod_wsgi. You'll probably want to start with the
|
||||||
|
`installation and configuration documentation`_.
|
||||||
|
|
||||||
|
.. _official mod_wsgi documentation: http://www.modwsgi.org/
|
||||||
|
.. _installation and configuration documentation: http://www.modwsgi.org/wiki/InstallationInstructions
|
||||||
|
|
||||||
|
Basic configuration
|
||||||
|
===================
|
||||||
|
|
||||||
|
Once you've got mod_wsgi installed and activated, edit your Apache server's
|
||||||
|
``httpd.conf`` file and add::
|
||||||
|
|
||||||
|
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
|
||||||
|
WSGIPythonPath /path/to/mysite.com
|
||||||
|
|
||||||
|
<Directory /path/to/mysite.com/mysite>
|
||||||
|
<Files wsgi.py>
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</Files>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The ``WSGIPythonPath`` line ensures that your project package is available for
|
||||||
|
import on the Python path; in other words, that ``import mysite`` works.
|
||||||
|
|
||||||
|
The ``<Directory>`` piece just ensures that Apache can access your
|
||||||
|
:file:`wsgi.py` file.
|
||||||
|
|
||||||
|
Next we'll need to ensure this :file:`wsgi.py` with a WSGI application object
|
||||||
|
exists. As of Django version 1.4, :djadmin:`startproject` will have created one
|
||||||
|
for you; otherwise, you'll need to create it. See the :doc:`WSGI overview
|
||||||
|
documentation</howto/deployment/wsgi/index>` for the default contents you
|
||||||
|
should put in this file, and what else you can add to it.
|
||||||
|
|
||||||
|
Using a virtualenv
|
||||||
|
==================
|
||||||
|
|
||||||
|
If you install your project's Python dependencies inside a `virtualenv`_,
|
||||||
|
you'll need to add the path to this virtualenv's ``site-packages`` directory to
|
||||||
|
your Python path as well. To do this, you can add another line to your
|
||||||
|
Apache configuration::
|
||||||
|
|
||||||
|
WSGIPythonPath /path/to/your/venv/lib/python2.X/site-packages
|
||||||
|
|
||||||
|
Make sure you give the correct path to your virtualenv, and replace
|
||||||
|
``python2.X`` with the correct Python version (e.g. ``python2.7``).
|
||||||
|
|
||||||
|
.. _virtualenv: http://www.virtualenv.org
|
||||||
|
|
||||||
|
Using mod_wsgi daemon mode
|
||||||
|
==========================
|
||||||
|
|
||||||
|
"Daemon mode" is the recommended mode for running mod_wsgi (on non-Windows
|
||||||
|
platforms). See the `official mod_wsgi documentation`_ for details on setting
|
||||||
|
up daemon mode. The only change required to the above configuration if you use
|
||||||
|
daemon mode is that you can't use ``WSGIPythonPath``; instead you should use
|
||||||
|
the ``python-path`` option to ``WSGIDaemonProcess``, for example::
|
||||||
|
|
||||||
|
WSGIDaemonProcess example.com python-path=/path/to/mysite.com:/path/to/venv/lib/python2.7/site-packages
|
||||||
|
|
||||||
|
.. _serving-files:
|
||||||
|
|
||||||
|
Serving files
|
||||||
|
=============
|
||||||
|
|
||||||
|
Django doesn't serve files itself; it leaves that job to whichever Web
|
||||||
|
server you choose.
|
||||||
|
|
||||||
|
We recommend using a separate Web server -- i.e., one that's not also running
|
||||||
|
Django -- for serving media. Here are some good choices:
|
||||||
|
|
||||||
|
* lighttpd_
|
||||||
|
* Nginx_
|
||||||
|
* TUX_
|
||||||
|
* A stripped-down version of Apache_
|
||||||
|
* Cherokee_
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This example sets up Django at the site root, but explicitly serves
|
||||||
|
``robots.txt``, ``favicon.ico``, any CSS file, and anything in the
|
||||||
|
``/static/`` and ``/media/`` URL space as a static file. All other URLs
|
||||||
|
will be served using mod_wsgi::
|
||||||
|
|
||||||
|
Alias /robots.txt /path/to/mysite.com/static/robots.txt
|
||||||
|
Alias /favicon.ico /path/to/mysite.com/static/favicon.ico
|
||||||
|
|
||||||
|
AliasMatch ^/([^/]*\.css) /path/to/mysite.com/static/styles/$1
|
||||||
|
|
||||||
|
Alias /media/ /path/to/mysite.com/media/
|
||||||
|
Alias /static/ /path/to/mysite.com/static/
|
||||||
|
|
||||||
|
<Directory /path/to/mysite.com/static>
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /path/to/mysite.com/media>
|
||||||
|
Order deny,allow
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
|
||||||
|
|
||||||
|
<Directory /path/to/mysite.com/mysite>
|
||||||
|
<Files wsgi.py>
|
||||||
|
Order allow,deny
|
||||||
|
Allow from all
|
||||||
|
</Files>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
.. _lighttpd: http://www.lighttpd.net/
|
||||||
|
.. _Nginx: http://wiki.nginx.org/Main
|
||||||
|
.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
|
||||||
|
.. _Apache: http://httpd.apache.org/
|
||||||
|
.. _Cherokee: http://www.cherokee-project.com/
|
||||||
|
|
||||||
|
.. More details on configuring a mod_wsgi site to serve static files can be found
|
||||||
|
.. in the mod_wsgi documentation on `hosting static files`_.
|
||||||
|
|
||||||
|
.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files
|
||||||
|
|
||||||
|
.. _serving-the-admin-files:
|
||||||
|
|
||||||
|
Serving the admin files
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Note that the Django development server automatically serves the static files
|
||||||
|
of the admin app (and any other installed apps), but this is not the case when
|
||||||
|
you use any other server arrangement. You're responsible for setting up Apache,
|
||||||
|
or whichever media server you're using, to serve the admin files.
|
||||||
|
|
||||||
|
The admin files live in (:file:`django/contrib/admin/static/admin`) of the
|
||||||
|
Django distribution.
|
||||||
|
|
||||||
|
We **strongly** recommend using :mod:`django.contrib.staticfiles` (along with
|
||||||
|
a Web server as outlined in the previous section) to handle the admin files, but
|
||||||
|
here are three other approaches:
|
||||||
|
|
||||||
|
1. Create a symbolic link to the admin static files from within your
|
||||||
|
document root (this may require ``+FollowSymLinks`` in your Apache
|
||||||
|
configuration).
|
||||||
|
|
||||||
|
2. Use an ``Alias`` directive, as demonstrated above, to alias the appropriate
|
||||||
|
URL (probably :setting:`STATIC_URL` + `admin/`) to the actual location of
|
||||||
|
the admin files.
|
||||||
|
|
||||||
|
3. Copy the admin static files so that they live within your Apache
|
||||||
|
document root.
|
|
@ -36,7 +36,7 @@ uWSGI model
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
uWSGI operates on a client-server model. Your Web server (ie. nginx, Apache)
|
uWSGI operates on a client-server model. Your Web server (ie. nginx, Apache)
|
||||||
communicates with a django-uwsgi "worker" process to serve dynamic contents.
|
communicates with a django-uwsgi "worker" process to serve dynamic content.
|
||||||
The Web server can communicate with the uWSGI process either:
|
The Web server can communicate with the uWSGI process either:
|
||||||
|
|
||||||
* directly by the uWSGI protocol through a socket created by uWSGI,
|
* directly by the uWSGI protocol through a socket created by uWSGI,
|
||||||
|
@ -48,9 +48,9 @@ systems), or it can use a TCP socket. What you choose is a matterr of
|
||||||
preference. Usually, a TCP socket is easier because connecting to a port
|
preference. Usually, a TCP socket is easier because connecting to a port
|
||||||
doesn't require special permissions.
|
doesn't require special permissions.
|
||||||
|
|
||||||
In the second case, the Web server doesn't need to do uWSGI protocol. It just
|
In the second case, the Web server doesn't need to speak the uWSGI protocol. It
|
||||||
needs to be able to proxy HTTP requests to the HTTP server built-in uWSGI.
|
just needs to be able to proxy HTTP requests to the HTTP server built-in uWSGI.
|
||||||
The procedure is the same than proxying any HTTP server. Note that the Web
|
The procedure is the same as proxying to any HTTP server. Note that the Web
|
||||||
server is a "reverse proxy" in this case.
|
server is a "reverse proxy" in this case.
|
||||||
|
|
||||||
Configuring the uWSGI server
|
Configuring the uWSGI server
|
||||||
|
@ -68,9 +68,9 @@ the uWSGI server.
|
||||||
on that file.
|
on that file.
|
||||||
|
|
||||||
uWSGI is highly configurable and thus there are many ways to start the
|
uWSGI is highly configurable and thus there are many ways to start the
|
||||||
process. For example, uwsgi version 0.9.6.8 provides a hundred switches.
|
process. For example, uwsgi version 0.9.6.8 provides a hundred switches. This
|
||||||
This guide demonstrates the most important of them, but does not intent to
|
guide demonstrates the most important of them, but is not a substitute the
|
||||||
substitute the official manual and online documentation.
|
official manual and online documentation.
|
||||||
|
|
||||||
uWSGI supports configuration through:
|
uWSGI supports configuration through:
|
||||||
|
|
||||||
|
@ -98,8 +98,8 @@ uWSGI server. This means:
|
||||||
|
|
||||||
* the uWSGI server can be restarted or reloaded independently from the Web
|
* the uWSGI server can be restarted or reloaded independently from the Web
|
||||||
server,
|
server,
|
||||||
* (except with Cheerokee), it is the role of the system administrator to make
|
* (except with Cherokee), it is the role of the system administrator to make
|
||||||
uWSGI to start on boot or reboot: either through tools like supervisor or
|
uWSGI start on boot or reboot: either through tools like supervisor or
|
||||||
daemontools, either directly at init level in a file like /etc/rc.local or
|
daemontools, either directly at init level in a file like /etc/rc.local or
|
||||||
/etc/conf.d/local
|
/etc/conf.d/local
|
||||||
|
|
||||||
|
@ -109,11 +109,11 @@ Managing uWSGI
|
||||||
Starting the server
|
Starting the server
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Example command line for a Web server that understand the uWSGI protocol::
|
Example command line for a Web server that understands the uWSGI protocol::
|
||||||
|
|
||||||
uwsgi --chdir=/path/to/your/project
|
uwsgi --chdir=/path/to/your/project
|
||||||
--module='django.core.handlers.wsgi:WSGIHandler()' \
|
--module='mysite.wsgi:application' \
|
||||||
--env DJANGO_SETTINGS_MODULE=settings \
|
--env DJANGO_SETTINGS_MODULE=mysite.settings \
|
||||||
--master --pidfile=/tmp/project-master.pid \
|
--master --pidfile=/tmp/project-master.pid \
|
||||||
--socket=127.0.0.1:49152 \ # can also be a file
|
--socket=127.0.0.1:49152 \ # can also be a file
|
||||||
--processes=5 \ # number of worker processes
|
--processes=5 \ # number of worker processes
|
||||||
|
@ -125,17 +125,27 @@ Example command line for a Web server that understand the uWSGI protocol::
|
||||||
--home=/path/to/virtual/env \ # optionnal path to a virtualenv
|
--home=/path/to/virtual/env \ # optionnal path to a virtualenv
|
||||||
--daemonize=/var/log/uwsgi/yourproject.log # background the process
|
--daemonize=/var/log/uwsgi/yourproject.log # background the process
|
||||||
|
|
||||||
Django specific options are:
|
This assumes that you have a top-level project package named ``mysite``, and
|
||||||
|
within it a module :file:`mysite/wsgi.py` that contains a WSGI ``application``
|
||||||
|
object. This is the layout you will have if you ran ``django-admin.py
|
||||||
|
startproject mysite`` (using your own project name in place of ``mysite``) with
|
||||||
|
a recent version of Django. If this file does not exist, you'll need to create
|
||||||
|
it. See the :doc:`/howto/deployment/wsgi/index` documentation for the default
|
||||||
|
contents you should put in this file, and what else you can add to it.
|
||||||
|
|
||||||
* ``chdir``: should be the path to your project
|
The Django-specific options here are:
|
||||||
* ``module``: uwsgi module to use
|
|
||||||
* ``pythonpath``: optional path to your project virtualenv
|
* ``chdir``: the path to the directory that needs to be on Python's import path; i.e. the directory containing the ``mysite`` package.
|
||||||
* ``env``: should contain at least ``DJANGO_SETTINGS_MODULE``
|
* ``module``: The WSGI module to use, probably the ``mysite.wsgi`` module which
|
||||||
|
:djadmin:`startproject` creates.
|
||||||
|
* ``env``: should probably contain at least ``DJANGO_SETTINGS_MODULE``
|
||||||
|
* ``home``: optional path to your project virtualenv
|
||||||
|
|
||||||
Example ini configuration file::
|
Example ini configuration file::
|
||||||
|
|
||||||
[uwsgi]
|
[uwsgi]
|
||||||
chdir=/path/to/your/project
|
chdir=/path/to/your/project
|
||||||
|
module='mysite.wsgi:application'
|
||||||
master=True
|
master=True
|
||||||
pidfile=/tmp/project-master.pid
|
pidfile=/tmp/project-master.pid
|
||||||
vacuum=True
|
vacuum=True
|
||||||
|
@ -157,7 +167,7 @@ Read more `uWSGI configuration examples
|
||||||
Reloading the daemon
|
Reloading the daemon
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
As mentioned above, the uWSGI master process is one of the core component of
|
As mentioned above, the uWSGI master process is one of the core components of
|
||||||
the uWSGI stack. The signal to brutally reload all the workers and the master
|
the uWSGI stack. The signal to brutally reload all the workers and the master
|
||||||
process is SIGTERM. Example command to brutally reload the uWSGI processes::
|
process is SIGTERM. Example command to brutally reload the uWSGI processes::
|
||||||
|
|
||||||
|
@ -167,7 +177,7 @@ Patching the daemon
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
One of the great advantages of uWSGI is its ability to gradually restart each
|
One of the great advantages of uWSGI is its ability to gradually restart each
|
||||||
worker without loosing any request.
|
worker without losing any requests.
|
||||||
|
|
||||||
For example, uWSGI can be signaled that worker should reload the code after
|
For example, uWSGI can be signaled that worker should reload the code after
|
||||||
handling their current request (if any) from bash::
|
handling their current request (if any) from bash::
|
||||||
|
@ -236,7 +246,7 @@ still experimental.
|
||||||
Troubleshooting
|
Troubleshooting
|
||||||
===============
|
===============
|
||||||
|
|
||||||
As usual, the first things to do is to check the logs. This implies:
|
As usual, the first thing to do is to check the logs. This implies:
|
||||||
|
|
||||||
* the web server log, which will indicate if it couldn't connect to the uWSGI
|
* the web server log, which will indicate if it couldn't connect to the uWSGI
|
||||||
process,
|
process,
|
||||||
|
@ -251,5 +261,5 @@ Typical gotchas:
|
||||||
killed with ``SIGKILL``, it won't remove the socket and pidfile when it is
|
killed with ``SIGKILL``, it won't remove the socket and pidfile when it is
|
||||||
interrupted. It is safe to remove them manually and to start uWSGI again in
|
interrupted. It is safe to remove them manually and to start uWSGI again in
|
||||||
that case.
|
that case.
|
||||||
* uWSGI can start the process on the foreground, this will make errors easily
|
* uWSGI can start the process in the foreground, this will make errors easily
|
||||||
visible to the system administrator.
|
visible to the system administrator.
|
|
@ -154,10 +154,9 @@ The development process
|
||||||
|
|
||||||
* **Deployment:**
|
* **Deployment:**
|
||||||
:doc:`Overview <howto/deployment/index>` |
|
:doc:`Overview <howto/deployment/index>` |
|
||||||
:doc:`Apache/mod_wsgi <howto/deployment/modwsgi>` |
|
:doc:`WSGI servers <howto/deployment/wsgi/index>` |
|
||||||
:doc:`uWSGI <howto/deployment/uwsgi>` |
|
|
||||||
:doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
|
|
||||||
:doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` |
|
:doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` |
|
||||||
|
:doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
|
||||||
:doc:`Apache authentication <howto/apache-auth>` |
|
:doc:`Apache authentication <howto/apache-auth>` |
|
||||||
:doc:`Handling static files <howto/static-files>` |
|
:doc:`Handling static files <howto/static-files>` |
|
||||||
:doc:`Tracking code errors by email <howto/error-reporting>`
|
:doc:`Tracking code errors by email <howto/error-reporting>`
|
||||||
|
|
|
@ -95,6 +95,7 @@ Let's look at what :djadmin:`startproject` created::
|
||||||
__init__.py
|
__init__.py
|
||||||
settings.py
|
settings.py
|
||||||
urls.py
|
urls.py
|
||||||
|
wsgi.py
|
||||||
|
|
||||||
.. admonition:: Doesn't match what you see?
|
.. admonition:: Doesn't match what you see?
|
||||||
|
|
||||||
|
@ -129,6 +130,9 @@ These files are:
|
||||||
"table of contents" of your Django-powered site. You can read more about
|
"table of contents" of your Django-powered site. You can read more about
|
||||||
URLs in :doc:`/topics/http/urls`.
|
URLs in :doc:`/topics/http/urls`.
|
||||||
|
|
||||||
|
* :file:`mysite/wsgi.py`: An entry-point for WSGI-compatible webservers to
|
||||||
|
serve your project. See :doc:`/howto/deployment/wsgi/index` for more details.
|
||||||
|
|
||||||
.. _more about packages: http://docs.python.org/tutorial/modules.html#packages
|
.. _more about packages: http://docs.python.org/tutorial/modules.html#packages
|
||||||
|
|
||||||
The development server
|
The development server
|
||||||
|
|
|
@ -54,7 +54,7 @@ Example::
|
||||||
number of ``processes`` instead.
|
number of ``processes`` instead.
|
||||||
|
|
||||||
For more information, please consult Django's
|
For more information, please consult Django's
|
||||||
:doc:`mod_wsgi documentation </howto/deployment/modwsgi>`.
|
:doc:`mod_wsgi documentation </howto/deployment/wsgi/modwsgi>`.
|
||||||
|
|
||||||
``mod_python``
|
``mod_python``
|
||||||
--------------
|
--------------
|
||||||
|
@ -62,8 +62,8 @@ For more information, please consult Django's
|
||||||
.. warning::
|
.. warning::
|
||||||
Support for mod_python will be deprecated in a future release of Django. If
|
Support for mod_python will be deprecated in a future release of Django. If
|
||||||
you are configuring a new deployment, you are strongly encouraged to
|
you are configuring a new deployment, you are strongly encouraged to
|
||||||
consider using :doc:`mod_wsgi </howto/deployment/modwsgi>` or any of the
|
consider using :doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` or any of
|
||||||
other :doc:`supported backends </howto/deployment/index>`.
|
the other :doc:`supported servers </howto/deployment/index>`.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
|
|
@ -504,6 +504,10 @@ supports the FastCGI protocol. See the :doc:`FastCGI deployment documentation
|
||||||
</howto/deployment/fastcgi>` for details. Requires the Python FastCGI module from
|
</howto/deployment/fastcgi>` for details. Requires the Python FastCGI module from
|
||||||
`flup`_.
|
`flup`_.
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
Internally, this wraps the WSGI application object specified by the
|
||||||
|
:setting:`WSGI_APPLICATION` setting.
|
||||||
|
|
||||||
.. _flup: http://www.saddi.com/software/flup/
|
.. _flup: http://www.saddi.com/software/flup/
|
||||||
|
|
||||||
The options accepted by this command are passed to the FastCGI library and
|
The options accepted by this command are passed to the FastCGI library and
|
||||||
|
@ -628,6 +632,10 @@ If you run this script as a user with normal privileges (recommended), you
|
||||||
might not have access to start a port on a low port number. Low port numbers
|
might not have access to start a port on a low port number. Low port numbers
|
||||||
are reserved for the superuser (root).
|
are reserved for the superuser (root).
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
This server uses the WSGI application object specified by the
|
||||||
|
:setting:`WSGI_APPLICATION` setting.
|
||||||
|
|
||||||
DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through
|
DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through
|
||||||
security audits or performance tests. (And that's how it's gonna stay. We're in
|
security audits or performance tests. (And that's how it's gonna stay. We're in
|
||||||
the business of making Web frameworks, not Web servers, so improving this
|
the business of making Web frameworks, not Web servers, so improving this
|
||||||
|
|
|
@ -2095,6 +2095,25 @@ A boolean that specifies whether to use the X-Forwarded-Host header in
|
||||||
preference to the Host header. This should only be enabled if a proxy
|
preference to the Host header. This should only be enabled if a proxy
|
||||||
which sets this header is in use.
|
which sets this header is in use.
|
||||||
|
|
||||||
|
.. setting:: WSGI_APPLICATION
|
||||||
|
|
||||||
|
WSGI_APPLICATION
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
The full Python path of the WSGI application object that Django's built-in
|
||||||
|
servers (e.g. :djadmin:`runserver`) will use. The :djadmin:`django-admin.py
|
||||||
|
startproject <startproject>` management command will create a simple
|
||||||
|
``wsgi.py`` file with an ``application`` callable in it, and point this setting
|
||||||
|
to that ``application``.
|
||||||
|
|
||||||
|
If not set, the return value of :func:`django.core.wsgi.get_wsgi_application`
|
||||||
|
will be used. In this case, the behavior of :djadmin:`runserver` will be
|
||||||
|
identical to previous Django versions.
|
||||||
|
|
||||||
.. setting:: YEAR_MONTH_FORMAT
|
.. setting:: YEAR_MONTH_FORMAT
|
||||||
|
|
||||||
YEAR_MONTH_FORMAT
|
YEAR_MONTH_FORMAT
|
||||||
|
|
|
@ -303,7 +303,7 @@ more flexible ``mod_wsgi`` backend.
|
||||||
|
|
||||||
If you are currently using the ``mod_python`` request handler, you are strongly
|
If you are currently using the ``mod_python`` request handler, you are strongly
|
||||||
encouraged to redeploy your Django instances using :doc:`mod_wsgi
|
encouraged to redeploy your Django instances using :doc:`mod_wsgi
|
||||||
</howto/deployment/modwsgi>`.
|
</howto/deployment/wsgi/modwsgi>`.
|
||||||
|
|
||||||
Function-based generic views
|
Function-based generic views
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -688,7 +688,7 @@ more flexible ``mod_wsgi`` backend.
|
||||||
|
|
||||||
If you are currently using the ``mod_python`` request handler, you
|
If you are currently using the ``mod_python`` request handler, you
|
||||||
should redeploy your Django projects using another request handler.
|
should redeploy your Django projects using another request handler.
|
||||||
:doc:`mod_wsgi </howto/deployment/modwsgi>` is the request handler
|
:doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` is the request handler
|
||||||
recommended by the Django project, but :doc:`FastCGI
|
recommended by the Django project, but :doc:`FastCGI
|
||||||
</howto/deployment/fastcgi>` is also supported. Support for
|
</howto/deployment/fastcgi>` is also supported. Support for
|
||||||
``mod_python`` deployment will be removed in Django 1.5.
|
``mod_python`` deployment will be removed in Django 1.5.
|
||||||
|
|
|
@ -403,6 +403,24 @@ prefix, some places without it), the imports will need to be cleaned up when
|
||||||
switching to the new ``manage.py``.
|
switching to the new ``manage.py``.
|
||||||
|
|
||||||
|
|
||||||
|
Improved WSGI support
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The :djadmin:`startproject` management command now adds a :file:`wsgi.py`
|
||||||
|
module to the initial project layout, containing a simple WSGI application that
|
||||||
|
can be used for :doc:`deploying with WSGI app
|
||||||
|
servers</howto/deployment/wsgi/index>`.
|
||||||
|
|
||||||
|
The :djadmin:`built-in development server<runserver>` now supports using an
|
||||||
|
externally-defined WSGI callable, so as to make it possible to run runserver
|
||||||
|
with the same WSGI configuration that is used for deployment. A new
|
||||||
|
:setting:`WSGI_APPLICATION` setting is available to configure which WSGI
|
||||||
|
callable :djadmin:`runserver` uses.
|
||||||
|
|
||||||
|
(The :djadmin:`runfcgi` management command also internally wraps the WSGI
|
||||||
|
callable configured via :setting:`WSGI_APPLICATION`.)
|
||||||
|
|
||||||
|
|
||||||
Minor features
|
Minor features
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ documentation to determine which mode is right for your setup. Make
|
||||||
sure you have Apache installed, with the mod_wsgi module activated.
|
sure you have Apache installed, with the mod_wsgi module activated.
|
||||||
Django will work with any version of Apache that supports mod_wsgi.
|
Django will work with any version of Apache that supports mod_wsgi.
|
||||||
|
|
||||||
See :doc:`How to use Django with mod_wsgi </howto/deployment/modwsgi>`
|
See :doc:`How to use Django with mod_wsgi </howto/deployment/wsgi/modwsgi>`
|
||||||
for information on how to configure mod_wsgi once you have it
|
for information on how to configure mod_wsgi once you have it
|
||||||
installed.
|
installed.
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ application what settings file to use. Do that with ``os.environ``::
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
|
||||||
|
|
||||||
Read the :doc:`Django mod_wsgi documentation
|
Read the :doc:`Django mod_wsgi documentation
|
||||||
</howto/deployment/modwsgi>` for more information and other common
|
</howto/deployment/wsgi/modwsgi>` for more information and other common
|
||||||
elements to a Django WSGI application.
|
elements to a Django WSGI application.
|
||||||
|
|
||||||
Default settings
|
Default settings
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.core.servers.basehttp import get_internal_wsgi_application
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
from django.test.utils import override_settings
|
||||||
|
from django.utils import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class WSGITest(TestCase):
|
||||||
|
urls = "regressiontests.wsgi.urls"
|
||||||
|
|
||||||
|
def test_get_wsgi_application(self):
|
||||||
|
"""
|
||||||
|
Verify that ``get_wsgi_application`` returns a functioning WSGI
|
||||||
|
callable.
|
||||||
|
|
||||||
|
"""
|
||||||
|
application = get_wsgi_application()
|
||||||
|
|
||||||
|
environ = RequestFactory()._base_environ(
|
||||||
|
PATH_INFO="/",
|
||||||
|
CONTENT_TYPE="text/html; charset=utf-8",
|
||||||
|
REQUEST_METHOD="GET"
|
||||||
|
)
|
||||||
|
|
||||||
|
response_data = {}
|
||||||
|
|
||||||
|
def start_response(status, headers):
|
||||||
|
response_data["status"] = status
|
||||||
|
response_data["headers"] = headers
|
||||||
|
|
||||||
|
response = application(environ, start_response)
|
||||||
|
|
||||||
|
self.assertEqual(response_data["status"], "200 OK")
|
||||||
|
self.assertEqual(
|
||||||
|
response_data["headers"],
|
||||||
|
[('Content-Type', 'text/html; charset=utf-8')])
|
||||||
|
self.assertEqual(
|
||||||
|
unicode(response),
|
||||||
|
u"Content-Type: text/html; charset=utf-8\n\nHello World!")
|
||||||
|
|
||||||
|
|
||||||
|
class GetInternalWSGIApplicationTest(unittest.TestCase):
|
||||||
|
@override_settings(WSGI_APPLICATION="regressiontests.wsgi.wsgi.application")
|
||||||
|
def test_success(self):
|
||||||
|
"""
|
||||||
|
If ``WSGI_APPLICATION`` is a dotted path, the referenced object is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
app = get_internal_wsgi_application()
|
||||||
|
|
||||||
|
from .wsgi import application
|
||||||
|
|
||||||
|
self.assertTrue(app is application)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(WSGI_APPLICATION=None)
|
||||||
|
def test_default(self):
|
||||||
|
"""
|
||||||
|
If ``WSGI_APPLICATION`` is ``None``, the return value of
|
||||||
|
``get_wsgi_application`` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Mock out get_wsgi_application so we know its return value is used
|
||||||
|
fake_app = object()
|
||||||
|
def mock_get_wsgi_app():
|
||||||
|
return fake_app
|
||||||
|
from django.core.servers import basehttp
|
||||||
|
_orig_get_wsgi_app = basehttp.get_wsgi_application
|
||||||
|
basehttp.get_wsgi_application = mock_get_wsgi_app
|
||||||
|
|
||||||
|
try:
|
||||||
|
app = get_internal_wsgi_application()
|
||||||
|
|
||||||
|
self.assertTrue(app is fake_app)
|
||||||
|
finally:
|
||||||
|
basehttp.get_wsgi_application = _orig_get_wsgi_app
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(WSGI_APPLICATION="regressiontests.wsgi.noexist.app")
|
||||||
|
def test_bad_module(self):
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as cm:
|
||||||
|
get_internal_wsgi_application()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
str(cm.exception),
|
||||||
|
"WSGI application 'regressiontests.wsgi.noexist.app' could not be loaded; could not import module 'regressiontests.wsgi.noexist': No module named noexist")
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(WSGI_APPLICATION="regressiontests.wsgi.wsgi.noexist")
|
||||||
|
def test_bad_name(self):
|
||||||
|
with self.assertRaises(ImproperlyConfigured) as cm:
|
||||||
|
get_internal_wsgi_application()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
str(cm.exception),
|
||||||
|
"WSGI application 'regressiontests.wsgi.wsgi.noexist' could not be loaded; can't find 'noexist' in module 'regressiontests.wsgi.wsgi': 'module' object has no attribute 'noexist'")
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
from django.conf.urls import url, patterns
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
def helloworld(request):
|
||||||
|
return HttpResponse("Hello World!")
|
||||||
|
|
||||||
|
urlpatterns = patterns(
|
||||||
|
"",
|
||||||
|
url("^$", helloworld)
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This is just to test finding, it doesn't have to be a real WSGI callable
|
||||||
|
application = object()
|
Loading…
Reference in New Issue