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

@ -407,6 +407,13 @@ X_FRAME_OPTIONS = 'SAMEORIGIN'
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 #
##############

View File

@ -99,6 +99,9 @@ MIDDLEWARE_CLASSES = (
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 = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.

View File

@ -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)

View File

@ -16,12 +16,14 @@ class Command(BaseRunserverCommand):
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)
use_static_handler = options.get('use_static_handler', True)
insecure_serving = options.get('insecure_serving', False)
if (settings.DEBUG and use_static_handler or
(use_static_handler and insecure_serving)):
handler = StaticFilesHandler(handler)
if use_static_handler and (settings.DEBUG or insecure_serving):
return StaticFilesHandler(handler)
return handler

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()

View File

@ -23,7 +23,7 @@ usage.
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
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
popular alternatives. Also, the `server arrangements wiki page`_ contains
details for several deployment strategies.

View File

@ -4,10 +4,9 @@ How to use Django with FastCGI, SCGI, or AJP
.. highlight:: bash
Although the current preferred setup for running Django is :doc:`Apache with
mod_wsgi </howto/deployment/modwsgi>`, many people use shared hosting, on
which protocols such as FastCGI, SCGI or AJP are the only viable options. In
some setups, these protocols may provide better performance than mod_wsgi_.
Although :doc:`WSGI</howto/deployment/wsgi/index>` is the preferred deployment
platform for Django, many people use shared hosting, on which protocols such as
FastCGI, SCGI or AJP are the only viable options.
.. 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
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
served with no startup time. While mod_wsgi can either be configured 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,
Like WSGI, FastCGI allows code to stay in memory, allowing requests to be
served with no startup time. While
e.g. :doc:`mod_wsgi</howto/deployment/wsgi/modwsgi>` can either be configured
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.
.. _mod_wsgi: http://code.google.com/p/modwsgi/
.. _mod_perl: http://perl.apache.org/
.. admonition:: Why run code in a separate process?

View File

@ -9,13 +9,12 @@ ways to easily deploy Django:
.. toctree::
:maxdepth: 1
modwsgi
uwsgi
wsgi/index
fastcgi
mod_python (deprecated) <modpython>
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.
.. seealso::

View File

@ -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
Django 1.5. If you are configuring a new deployment, you are
strongly encouraged to consider using :doc:`mod_wsgi
</howto/deployment/modwsgi>` or any of the other :doc:`supported
backends </howto/deployment/index>`.
</howto/deployment/wsgi/modwsgi>` or any of the other :doc:`supported
servers </howto/deployment/index>`.
.. highlight:: apache
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
: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
Apache and loads Python code into memory when the server starts. Code stays in

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -36,7 +36,7 @@ uWSGI model
-----------
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:
* 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
doesn't require special permissions.
In the second case, the Web server doesn't need to do uWSGI protocol. It 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
In the second case, the Web server doesn't need to speak the uWSGI protocol. It
just needs to be able to proxy HTTP requests to the HTTP server built-in uWSGI.
The procedure is the same as proxying to any HTTP server. Note that the Web
server is a "reverse proxy" in this case.
Configuring the uWSGI server
@ -68,9 +68,9 @@ the uWSGI server.
on that file.
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.
This guide demonstrates the most important of them, but does not intent to
substitute the official manual and online documentation.
process. For example, uwsgi version 0.9.6.8 provides a hundred switches. This
guide demonstrates the most important of them, but is not a substitute the
official manual and online documentation.
uWSGI supports configuration through:
@ -98,8 +98,8 @@ uWSGI server. This means:
* the uWSGI server can be restarted or reloaded independently from the Web
server,
* (except with Cheerokee), it is the role of the system administrator to make
uWSGI to start on boot or reboot: either through tools like supervisor or
* (except with Cherokee), it is the role of the system administrator to make
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
/etc/conf.d/local
@ -109,11 +109,11 @@ Managing uWSGI
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
--module='django.core.handlers.wsgi:WSGIHandler()' \
--env DJANGO_SETTINGS_MODULE=settings \
--module='mysite.wsgi:application' \
--env DJANGO_SETTINGS_MODULE=mysite.settings \
--master --pidfile=/tmp/project-master.pid \
--socket=127.0.0.1:49152 \ # can also be a file
--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
--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
* ``module``: uwsgi module to use
* ``pythonpath``: optional path to your project virtualenv
* ``env``: should contain at least ``DJANGO_SETTINGS_MODULE``
The Django-specific options here are:
* ``chdir``: the path to the directory that needs to be on Python's import path; i.e. the directory containing the ``mysite`` package.
* ``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::
[uwsgi]
chdir=/path/to/your/project
module='mysite.wsgi:application'
master=True
pidfile=/tmp/project-master.pid
vacuum=True
@ -157,7 +167,7 @@ Read more `uWSGI configuration examples
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
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
worker without loosing any request.
worker without losing any requests.
For example, uWSGI can be signaled that worker should reload the code after
handling their current request (if any) from bash::
@ -236,7 +246,7 @@ still experimental.
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
process,
@ -251,5 +261,5 @@ Typical gotchas:
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
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.

View File

@ -154,10 +154,9 @@ The development process
* **Deployment:**
:doc:`Overview <howto/deployment/index>` |
:doc:`Apache/mod_wsgi <howto/deployment/modwsgi>` |
:doc:`uWSGI <howto/deployment/uwsgi>` |
:doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
:doc:`WSGI servers <howto/deployment/wsgi/index>` |
:doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` |
:doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
:doc:`Apache authentication <howto/apache-auth>` |
:doc:`Handling static files <howto/static-files>` |
:doc:`Tracking code errors by email <howto/error-reporting>`

View File

@ -95,6 +95,7 @@ Let's look at what :djadmin:`startproject` created::
__init__.py
settings.py
urls.py
wsgi.py
.. 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
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
The development server

View File

@ -54,7 +54,7 @@ Example::
number of ``processes`` instead.
For more information, please consult Django's
:doc:`mod_wsgi documentation </howto/deployment/modwsgi>`.
:doc:`mod_wsgi documentation </howto/deployment/wsgi/modwsgi>`.
``mod_python``
--------------
@ -62,8 +62,8 @@ For more information, please consult Django's
.. warning::
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
consider using :doc:`mod_wsgi </howto/deployment/modwsgi>` or any of the
other :doc:`supported backends </howto/deployment/index>`.
consider using :doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` or any of
the other :doc:`supported servers </howto/deployment/index>`.
Example::

View File

@ -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
`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/
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
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
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

View File

@ -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
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
YEAR_MONTH_FORMAT

View File

@ -303,7 +303,7 @@ more flexible ``mod_wsgi`` backend.
If you are currently using the ``mod_python`` request handler, you are strongly
encouraged to redeploy your Django instances using :doc:`mod_wsgi
</howto/deployment/modwsgi>`.
</howto/deployment/wsgi/modwsgi>`.
Function-based generic views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -688,7 +688,7 @@ more flexible ``mod_wsgi`` backend.
If you are currently using the ``mod_python`` request handler, you
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
</howto/deployment/fastcgi>` is also supported. Support for
``mod_python`` deployment will be removed in Django 1.5.

View File

@ -403,6 +403,24 @@ prefix, some places without it), the imports will need to be cleaned up when
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
~~~~~~~~~~~~~~

View File

@ -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.
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
installed.

View File

@ -75,7 +75,7 @@ application what settings file to use. Do that with ``os.environ``::
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
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.
Default settings

View File

View File

View File

@ -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'")

View File

@ -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)
)

View File

@ -0,0 +1,2 @@
# This is just to test finding, it doesn't have to be a real WSGI callable
application = object()