Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16360 -- Added WSGI entrypoint to startproject layout, and ena…

…bled 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
  • Loading branch information...
commit 145a77edc999fd5f1a53bc5bfd6b581386950074 1 parent dca81ad
Carl Meyer authored October 22, 2011

Showing 34 changed files with 635 additions and 208 deletions. Show diff stats Hide diff stats

  1. 7  django/conf/global_settings.py
  2. 3  django/conf/project_template/project_name/settings.py
  3. 28  django/conf/project_template/project_name/wsgi.py
  4. 10  django/contrib/staticfiles/management/commands/runserver.py
  5. 4  django/core/handlers/base.py
  6. 5  django/core/handlers/wsgi.py
  7. 5  django/core/management/commands/runserver.py
  8. 40  django/core/servers/basehttp.py
  9. 4  django/core/servers/fastcgi.py
  10. 13  django/core/wsgi.py
  11. 2  docs/faq/install.txt
  12. 17  docs/howto/deployment/fastcgi.txt
  13. 5  docs/howto/deployment/index.txt
  14. 6  docs/howto/deployment/modpython.txt
  15. 147  docs/howto/deployment/modwsgi.txt
  16. 66  docs/howto/deployment/wsgi/gunicorn.txt
  17. 72  docs/howto/deployment/wsgi/index.txt
  18. 175  docs/howto/deployment/wsgi/modwsgi.txt
  19. 52  docs/howto/deployment/{ → wsgi}/uwsgi.txt
  20. 5  docs/index.txt
  21. 4  docs/intro/tutorial01.txt
  22. 6  docs/ref/contrib/gis/deployment.txt
  23. 8  docs/ref/django-admin.txt
  24. 19  docs/ref/settings.txt
  25. 2  docs/releases/1.3-alpha-1.txt
  26. 2  docs/releases/1.3.txt
  27. 18  docs/releases/1.4.txt
  28. 2  docs/topics/install.txt
  29. 2  docs/topics/settings.txt
  30. 0  tests/regressiontests/wsgi/__init__.py
  31. 0  tests/regressiontests/wsgi/models.py
  32. 102  tests/regressiontests/wsgi/tests.py
  33. 10  tests/regressiontests/wsgi/urls.py
  34. 2  tests/regressiontests/wsgi/wsgi.py
7  django/conf/global_settings.py
@@ -407,6 +407,13 @@
407 407
 
408 408
 USE_X_FORWARDED_HOST = False
409 409
 
  410
+# The Python dotted path to the WSGI application that Django's internal servers
  411
+# (runserver, runfcgi) will use. If `None`, the return value of
  412
+# 'django.core.wsgi.get_wsgi_application' is used, thus preserving the same
  413
+# behavior as previous versions of Django. Otherwise this should point to an
  414
+# actual WSGI application object.
  415
+WSGI_APPLICATION = None
  416
+
410 417
 ##############
411 418
 # MIDDLEWARE #
412 419
 ##############
3  django/conf/project_template/project_name/settings.py
@@ -99,6 +99,9 @@
99 99
 
100 100
 ROOT_URLCONF = '{{ project_name }}.urls'
101 101
 
  102
+# Python dotted path to the WSGI application used by Django's runserver.
  103
+WSGI_APPLICATION = '{{ project_name }}.wsgi.application'
  104
+
102 105
 TEMPLATE_DIRS = (
103 106
     # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
104 107
     # Always use forward slashes, even on Windows.
28  django/conf/project_template/project_name/wsgi.py
... ...
@@ -0,0 +1,28 @@
  1
+"""
  2
+WSGI config for {{ project_name }} project.
  3
+
  4
+This module contains the WSGI application used by Django's development server
  5
+and any production WSGI deployments. It should expose a module-level variable
  6
+named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
  7
+this application via the ``WSGI_APPLICATION`` setting.
  8
+
  9
+Usually you will have the standard Django WSGI application here, but it also
  10
+might make sense to replace the whole Django WSGI application with a custom one
  11
+that later delegates to the Django one. For example, you could introduce WSGI
  12
+middleware here, or combine a Django application with an application of another
  13
+framework.
  14
+
  15
+"""
  16
+import os
  17
+
  18
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
  19
+
  20
+# This application object is used by any WSGI server configured to use this
  21
+# file. This includes Django's development server, if the WSGI_APPLICATION
  22
+# setting points here.
  23
+from django.core.wsgi import get_wsgi_application
  24
+application = get_wsgi_application()
  25
+
  26
+# Apply WSGI middleware here.
  27
+# from helloworld.wsgi import HelloWorldApplication
  28
+# application = HelloWorldApplication(application)
10  django/contrib/staticfiles/management/commands/runserver.py
@@ -16,12 +16,14 @@ class Command(BaseRunserverCommand):
16 16
 
17 17
     def get_handler(self, *args, **options):
18 18
         """
19  
-        Returns the static files serving handler.
  19
+        Returns the static files serving handler wrapping the default handler,
  20
+        if static files should be served. Otherwise just returns the default
  21
+        handler.
  22
+
20 23
         """
21 24
         handler = super(Command, self).get_handler(*args, **options)
22 25
         use_static_handler = options.get('use_static_handler', True)
23 26
         insecure_serving = options.get('insecure_serving', False)
24  
-        if (settings.DEBUG and use_static_handler or
25  
-                (use_static_handler and insecure_serving)):
26  
-            handler = StaticFilesHandler(handler)
  27
+        if use_static_handler and (settings.DEBUG or insecure_serving):
  28
+            return StaticFilesHandler(handler)
27 29
         return handler
4  django/core/handlers/base.py
@@ -242,8 +242,8 @@ def get_script_name(environ):
242 242
     Returns the equivalent of the HTTP request's SCRIPT_NAME environment
243 243
     variable. If Apache mod_rewrite has been used, returns what would have been
244 244
     the script name prior to any rewriting (so it's the script name as seen
245  
-    from the client's perspective), unless FORCE_SCRIPT_NAME is set (to
246  
-    anything).
  245
+    from the client's perspective), unless the FORCE_SCRIPT_NAME setting is
  246
+    set (to anything).
247 247
     """
248 248
     from django.conf import settings
249 249
     if settings.FORCE_SCRIPT_NAME is not None:
5  django/core/handlers/wsgi.py
@@ -124,6 +124,7 @@ def readline(self, size=None):
124 124
         self.buffer = sio.read()
125 125
         return line
126 126
 
  127
+
127 128
 class WSGIRequest(http.HttpRequest):
128 129
     def __init__(self, environ):
129 130
         script_name = base.get_script_name(environ)
@@ -202,13 +203,12 @@ def _get_files(self):
202 203
     FILES = property(_get_files)
203 204
     REQUEST = property(_get_request)
204 205
 
  206
+
205 207
 class WSGIHandler(base.BaseHandler):
206 208
     initLock = Lock()
207 209
     request_class = WSGIRequest
208 210
 
209 211
     def __call__(self, environ, start_response):
210  
-        from django.conf import settings
211  
-
212 212
         # Set up middleware if needed. We couldn't do this earlier, because
213 213
         # settings weren't available.
214 214
         if self._request_middleware is None:
@@ -253,4 +253,3 @@ def __call__(self, environ, start_response):
253 253
             response_headers.append(('Set-Cookie', str(c.output(header=''))))
254 254
         start_response(status, response_headers)
255 255
         return response
256  
-
5  django/core/management/commands/runserver.py
@@ -5,8 +5,7 @@
5 5
 import socket
6 6
 
7 7
 from django.core.management.base import BaseCommand, CommandError
8  
-from django.core.handlers.wsgi import WSGIHandler
9  
-from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException
  8
+from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException, get_internal_wsgi_application
10 9
 from django.utils import autoreload
11 10
 
12 11
 naiveip_re = re.compile(r"""^(?:
@@ -37,7 +36,7 @@ def get_handler(self, *args, **options):
37 36
         """
38 37
         Returns the default WSGI handler for the runner.
39 38
         """
40  
-        return WSGIHandler()
  39
+        return get_internal_wsgi_application()
41 40
 
42 41
     def handle(self, addrport='', *args, **options):
43 42
         self.use_ipv6 = options.get('use_ipv6')
40  django/core/servers/basehttp.py
@@ -18,7 +18,10 @@
18 18
 from wsgiref.util import FileWrapper   # for backwards compatibility
19 19
 
20 20
 import django
  21
+from django.core.exceptions import ImproperlyConfigured
21 22
 from django.core.management.color import color_style
  23
+from django.core.wsgi import get_wsgi_application
  24
+from django.utils.importlib import import_module
22 25
 from django.utils._os import safe_join
23 26
 from django.views import static
24 27
 
@@ -27,6 +30,43 @@
27 30
 __all__ = ['WSGIServer', 'WSGIRequestHandler']
28 31
 
29 32
 
  33
+def get_internal_wsgi_application():
  34
+    """
  35
+    Loads and returns the WSGI application as configured by the user in
  36
+    ``settings.WSGI_APPLICATION``. With the default ``startproject`` layout,
  37
+    this will be the ``application`` object in ``projectname/wsgi.py``.
  38
+
  39
+    This function, and the ``WSGI_APPLICATION`` setting itself, are only useful
  40
+    for Django's internal servers (runserver, runfcgi); external WSGI servers
  41
+    should just be configured to point to the correct application object
  42
+    directly.
  43
+
  44
+    If settings.WSGI_APPLICATION is not set (is ``None``), we just return
  45
+    whatever ``django.core.wsgi.get_wsgi_application`` returns.
  46
+
  47
+    """
  48
+    from django.conf import settings
  49
+    app_path = getattr(settings, 'WSGI_APPLICATION')
  50
+    if app_path is None:
  51
+        return get_wsgi_application()
  52
+    module_name, attr = app_path.rsplit('.', 1)
  53
+    try:
  54
+        mod = import_module(module_name)
  55
+    except ImportError, e:
  56
+        raise ImproperlyConfigured(
  57
+            "WSGI application '%s' could not be loaded; "
  58
+            "could not import module '%s': %s" % (app_path, module_name, e))
  59
+    try:
  60
+        app = getattr(mod, attr)
  61
+    except AttributeError, e:
  62
+        raise ImproperlyConfigured(
  63
+            "WSGI application '%s' could not be loaded; "
  64
+            "can't find '%s' in module '%s': %s"
  65
+            % (app_path, attr, module_name, e))
  66
+
  67
+    return app
  68
+
  69
+
30 70
 class WSGIServerException(Exception):
31 71
     pass
32 72
 
4  django/core/servers/fastcgi.py
@@ -139,7 +139,7 @@ def runfastcgi(argset=[], **kwargs):
139 139
         return False
140 140
 
141 141
     # Prep up and go
142  
-    from django.core.handlers.wsgi import WSGIHandler
  142
+    from django.core.servers.basehttp import get_internal_wsgi_application
143 143
 
144 144
     if options["host"] and options["port"] and not options["socket"]:
145 145
         wsgi_opts['bindAddress'] = (options["host"], int(options["port"]))
@@ -178,7 +178,7 @@ def runfastcgi(argset=[], **kwargs):
178 178
         fp.write("%d\n" % os.getpid())
179 179
         fp.close()
180 180
 
181  
-    WSGIServer(WSGIHandler(), **wsgi_opts).run()
  181
+    WSGIServer(get_internal_wsgi_application(), **wsgi_opts).run()
182 182
 
183 183
 if __name__ == '__main__':
184 184
     runfastcgi(sys.argv[1:])
13  django/core/wsgi.py
... ...
@@ -0,0 +1,13 @@
  1
+from django.core.handlers.wsgi import WSGIHandler
  2
+
  3
+
  4
+def get_wsgi_application():
  5
+    """
  6
+    The public interface to Django's WSGI support. Should return a WSGI
  7
+    callable.
  8
+
  9
+    Allows us to avoid making django.core.handlers.WSGIHandler public API, in
  10
+    case the internal WSGI implementation changes or moves in the future.
  11
+
  12
+    """
  13
+    return WSGIHandler()
2  docs/faq/install.txt
@@ -23,7 +23,7 @@ usage.
23 23
 For a development environment -- if you just want to experiment with Django --
24 24
 you don't need to have a separate Web server installed; Django comes with its
25 25
 own lightweight development server. For a production environment, Django follows
26  
-the WSGI spec, :pep:`333`, which means it can run on a variety of server
  26
+the WSGI spec, :pep:`3333`, which means it can run on a variety of server
27 27
 platforms. See :doc:`Deploying Django </howto/deployment/index>` for some
28 28
 popular alternatives. Also, the `server arrangements wiki page`_ contains
29 29
 details for several deployment strategies.
17  docs/howto/deployment/fastcgi.txt
@@ -4,10 +4,9 @@ How to use Django with FastCGI, SCGI, or AJP
4 4
 
5 5
 .. highlight:: bash
6 6
 
7  
-Although the current preferred setup for running Django is :doc:`Apache with
8  
-mod_wsgi </howto/deployment/modwsgi>`, many people use shared hosting, on
9  
-which protocols such as FastCGI, SCGI or AJP are the only viable options. In
10  
-some setups, these protocols may provide better performance than mod_wsgi_.
  7
+Although :doc:`WSGI</howto/deployment/wsgi/index>` is the preferred deployment
  8
+platform for Django, many people use shared hosting, on which protocols such as
  9
+FastCGI, SCGI or AJP are the only viable options.
11 10
 
12 11
 .. admonition:: Note
13 12
 
@@ -20,13 +19,13 @@ serve pages to a Web server. The Web server delegates the incoming Web requests
20 19
 (via a socket) to FastCGI, which executes the code and passes the response back
21 20
 to the Web server, which, in turn, passes it back to the client's Web browser.
22 21
 
23  
-Like mod_wsgi, FastCGI allows code to stay in memory, allowing requests to be
24  
-served with no startup time. While mod_wsgi can either be configured embedded
25  
-in the Apache Web server process or as a separate daemon process, a FastCGI
26  
-process never runs inside the Web server process, always in a separate,
  22
+Like WSGI, FastCGI allows code to stay in memory, allowing requests to be
  23
+served with no startup time. While
  24
+e.g. :doc:`mod_wsgi</howto/deployment/wsgi/modwsgi>` can either be configured
  25
+embedded in the Apache Web server process or as a separate daemon process, a
  26
+FastCGI process never runs inside the Web server process, always in a separate,
27 27
 persistent process.
28 28
 
29  
-.. _mod_wsgi: http://code.google.com/p/modwsgi/
30 29
 .. _mod_perl: http://perl.apache.org/
31 30
 
32 31
 .. admonition:: Why run code in a separate process?
5  docs/howto/deployment/index.txt
@@ -9,13 +9,12 @@ ways to easily deploy Django:
9 9
 .. toctree::
10 10
    :maxdepth: 1
11 11
 
12  
-   modwsgi
13  
-   uwsgi
  12
+   wsgi/index
14 13
    fastcgi
15 14
    mod_python (deprecated) <modpython>
16 15
 
17 16
 If you're new to deploying Django and/or Python, we'd recommend you try
18  
-:doc:`mod_wsgi </howto/deployment/modwsgi>` first. In most cases it'll be
  17
+:doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` first. In most cases it'll be
19 18
 the easiest, fastest, and most stable deployment choice.
20 19
 
21 20
 .. seealso::
6  docs/howto/deployment/modpython.txt
@@ -7,14 +7,14 @@ How to use Django with Apache and mod_python
7 7
     Support for mod_python has been deprecated, and will be removed in
8 8
     Django 1.5. If you are configuring a new deployment, you are
9 9
     strongly encouraged to consider using :doc:`mod_wsgi
10  
-    </howto/deployment/modwsgi>` or any of the other :doc:`supported
11  
-    backends </howto/deployment/index>`.
  10
+    </howto/deployment/wsgi/modwsgi>` or any of the other :doc:`supported
  11
+    servers </howto/deployment/index>`.
12 12
 
13 13
 .. highlight:: apache
14 14
 
15 15
 The `mod_python`_ module for Apache_ can be used to deploy Django to a
16 16
 production server, although it has been mostly superseded by the simpler
17  
-:doc:`mod_wsgi deployment option </howto/deployment/modwsgi>`.
  17
+:doc:`mod_wsgi deployment option </howto/deployment/wsgi/modwsgi>`.
18 18
 
19 19
 mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
20 20
 Apache and loads Python code into memory when the server starts. Code stays in
147  docs/howto/deployment/modwsgi.txt
... ...
@@ -1,147 +0,0 @@
1  
-==========================================
2  
-How to use Django with Apache and mod_wsgi
3  
-==========================================
4  
-
5  
-Deploying Django with Apache_ and `mod_wsgi`_ is the recommended way to get
6  
-Django into production.
7  
-
8  
-.. _Apache: http://httpd.apache.org/
9  
-.. _mod_wsgi: http://code.google.com/p/modwsgi/
10  
-
11  
-mod_wsgi is an Apache module which can be used to host any Python application
12  
-which supports the Python WSGI interface described in :pep:`3333`, including
13  
-Django. Django will work with any version of Apache which supports mod_wsgi.
14  
-
15  
-The `official mod_wsgi documentation`_ is fantastic; it's your source for all
16  
-the details about how to use mod_wsgi. You'll probably want to start with the
17  
-`installation and configuration documentation`_.
18  
-
19  
-.. _official mod_wsgi documentation: http://code.google.com/p/modwsgi/
20  
-.. _installation and configuration documentation: http://code.google.com/p/modwsgi/wiki/InstallationInstructions
21  
-
22  
-Basic configuration
23  
-===================
24  
-
25  
-Once you've got mod_wsgi installed and activated, edit your ``httpd.conf`` file
26  
-and add::
27  
-
28  
-    WSGIScriptAlias / /path/to/mysite/apache/django.wsgi
29  
-
30  
-The first bit above is the url you want to be serving your application at (``/``
31  
-indicates the root url), and the second is the location of a "WSGI file" -- see
32  
-below -- on your system, usually inside of your project. This tells Apache
33  
-to serve any request below the given URL using the WSGI application defined by that file.
34  
-
35  
-Next we'll need to actually create this WSGI application, so create the file
36  
-mentioned in the second part of ``WSGIScriptAlias`` and add::
37  
-
38  
-    import os
39  
-    import sys
40  
-
41  
-    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
42  
-
43  
-    import django.core.handlers.wsgi
44  
-    application = django.core.handlers.wsgi.WSGIHandler()
45  
-
46  
-If your project is not on your ``PYTHONPATH`` by default you can add::
47  
-
48  
-    path = '/path/to/mysite'
49  
-    if path not in sys.path:
50  
-        sys.path.append(path)
51  
-
52  
-just below the ``import sys`` line to place your project on the path. Remember to
53  
-replace 'mysite.settings' with your correct settings file, and '/path/to/mysite'
54  
-with your own project's location.
55  
-
56  
-.. _serving-files:
57  
-
58  
-Serving files
59  
-=============
60  
-
61  
-Django doesn't serve files itself; it leaves that job to whichever Web
62  
-server you choose.
63  
-
64  
-We recommend using a separate Web server -- i.e., one that's not also running
65  
-Django -- for serving media. Here are some good choices:
66  
-
67  
-* lighttpd_
68  
-* Nginx_
69  
-* TUX_
70  
-* A stripped-down version of Apache_
71  
-* Cherokee_
72  
-
73  
-If, however, you have no option but to serve media files on the same Apache
74  
-``VirtualHost`` as Django, you can set up Apache to serve some URLs as
75  
-static media, and others using the mod_wsgi interface to Django.
76  
-
77  
-This example sets up Django at the site root, but explicitly serves
78  
-``robots.txt``, ``favicon.ico``, any CSS file, and anything in the
79  
-``/static/`` and ``/media/`` URL space as a static file. All other URLs
80  
-will be served using mod_wsgi::
81  
-
82  
-    Alias /robots.txt /usr/local/wsgi/static/robots.txt
83  
-    Alias /favicon.ico /usr/local/wsgi/static/favicon.ico
84  
-
85  
-    AliasMatch ^/([^/]*\.css) /usr/local/wsgi/static/styles/$1
86  
-
87  
-    Alias /media/ /usr/local/wsgi/media/
88  
-    Alias /static/ /usr/local/wsgi/static/
89  
-
90  
-    <Directory /usr/local/wsgi/static>
91  
-    Order deny,allow
92  
-    Allow from all
93  
-    </Directory>
94  
-
95  
-    <Directory /usr/local/wsgi/media>
96  
-    Order deny,allow
97  
-    Allow from all
98  
-    </Directory>
99  
-
100  
-    WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi
101  
-
102  
-    <Directory /usr/local/wsgi/scripts>
103  
-    Order allow,deny
104  
-    Allow from all
105  
-    </Directory>
106  
-
107  
-.. _lighttpd: http://www.lighttpd.net/
108  
-.. _Nginx: http://wiki.nginx.org/Main
109  
-.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
110  
-.. _Apache: http://httpd.apache.org/
111  
-.. _Cherokee: http://www.cherokee-project.com/
112  
-
113  
-.. More details on configuring a mod_wsgi site to serve static files can be found
114  
-.. in the mod_wsgi documentation on `hosting static files`_.
115  
-
116  
-.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files
117  
-
118  
-.. _serving-the-admin-files:
119  
-
120  
-Serving the admin files
121  
-=======================
122  
-
123  
-Note that the Django development server automagically serves the static files
124  
-of the admin app, but this is not the case when you use any other server
125  
-arrangement. You're responsible for setting up Apache, or whichever media
126  
-server you're using, to serve the admin files.
127  
-
128  
-The admin files live in (:file:`django/contrib/admin/static/admin`) of the
129  
-Django distribution.
130  
-
131  
-We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
132  
-the admin files, but here are two other approaches:
133  
-
134  
-1. Create a symbolic link to the admin static files from within your
135  
-   document root.
136  
-
137  
-2. Or, copy the admin static files so that they live within your Apache
138  
-   document root.
139  
-
140  
-Details
141  
-=======
142  
-
143  
-For more details, see the `mod_wsgi documentation on Django integration`_,
144  
-which explains the above in more detail, and walks through all the various
145  
-options you've got when deploying under mod_wsgi.
146  
-
147  
-.. _mod_wsgi documentation on Django integration: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
66  docs/howto/deployment/wsgi/gunicorn.txt
... ...
@@ -0,0 +1,66 @@
  1
+===============================
  2
+How to use Django with Gunicorn
  3
+===============================
  4
+
  5
+.. highlight:: bash
  6
+
  7
+Gunicorn_ ('Green Unicorn') is a pure-Python WSGI server for UNIX. It has no
  8
+dependencies and is easy to install and use.
  9
+
  10
+.. _Gunicorn: http://gunicorn.org/
  11
+
  12
+There are two ways to use Gunicorn with Django. One is to have Gunicorn treat
  13
+Django as just another WSGI application. The second is to use Gunicorn's
  14
+special `integration with Django`_.
  15
+
  16
+.. _integration with Django: http://gunicorn.org/run.html#django-manage-py_
  17
+
  18
+Installing Gunicorn
  19
+===================
  20
+
  21
+Installing gunicorn is as easy as ``pip install gunicorn``. For more details,
  22
+see the `gunicorn documentation`_.
  23
+
  24
+.. _gunicorn documentation: http://gunicorn.org/install.html
  25
+
  26
+Running Django in Gunicorn as a generic WSGI application
  27
+========================================================
  28
+
  29
+When Gunicorn is installed, a ``gunicorn`` command is available which starts
  30
+the Gunicorn server process. At its simplest, gunicorn just needs to be called
  31
+with a the location of a WSGI application object.::
  32
+
  33
+    gunicorn [OPTIONS] APP_MODULE
  34
+
  35
+Where ``APP_MODULE`` is of the pattern ``MODULE_NAME:VARIABLE_NAME``. The
  36
+module name should be a full dotted path. The variable name refers to a WSGI
  37
+callable that should be found in the specified module.
  38
+
  39
+So for a typical Django project, invoking gunicorn would look like::
  40
+
  41
+    gunicorn myproject.wsgi:application
  42
+
  43
+(This requires that your project be on the Python path; the simplest way to
  44
+ensure that is to run this command from the same directory as your
  45
+``manage.py`` file.)
  46
+
  47
+
  48
+Using Gunicorn's Django integration
  49
+===================================
  50
+
  51
+To use Gunicorn's built-in Django integration, first add ``"gunicorn"`` to
  52
+:setting:`INSTALLED_APPS`. Then run ``python manage.py run_gunicorn``.
  53
+
  54
+This provides a few Django-specific niceties:
  55
+
  56
+* sets the gunicorn process name to be that of the project
  57
+
  58
+* validates installed models
  59
+
  60
+* allows an ``--adminmedia`` option for passing in the location of the
  61
+  admin media files, mimicing the behavior of runserver.
  62
+
  63
+See Gunicorn's `deployment documentation`_ for additional tips on starting and
  64
+maintaining the Gunicorn server.
  65
+
  66
+.. _deployment documentation: http://gunicorn.org/deploy.html
72  docs/howto/deployment/wsgi/index.txt
... ...
@@ -0,0 +1,72 @@
  1
+=======================
  2
+How to deploy with WSGI
  3
+=======================
  4
+
  5
+Django's primary deployment platform is WSGI_, the Python standard for web
  6
+servers and applications.
  7
+
  8
+.. _WSGI: http://www.wsgi.org
  9
+
  10
+Django's :djadmin:`startproject` management command sets up a simple default
  11
+WSGI configuration for you, which you can tweak as needed for your project, and
  12
+direct any WSGI-compliant webserver to use. Django includes getting-started
  13
+documentation for the following WSGI servers:
  14
+
  15
+.. toctree::
  16
+   :maxdepth: 1
  17
+
  18
+   modwsgi
  19
+   gunicorn
  20
+   uwsgi
  21
+
  22
+The ``application`` object
  23
+--------------------------
  24
+
  25
+One key concept of deploying with WSGI is to specify a central ``application``
  26
+callable object which the webserver uses to communicate with your code. This is
  27
+commonly specified as an object named ``application`` in a Python module
  28
+accessible to the server.
  29
+
  30
+.. versionchanged:: 1.4
  31
+
  32
+The :djadmin:`startproject` command creates a :file:`projectname/wsgi.py` that
  33
+contains such an application callable.
  34
+
  35
+.. note::
  36
+
  37
+   Upgrading from a previous release of Django and don't have a :file:`wsgi.py`
  38
+   file in your project? You can simply add one to your project's top-level
  39
+   Python package (probably next to :file:`settings.py` and :file:`urls.py`)
  40
+   with the contents below. If you want :djadmin:`runserver` to also make use
  41
+   of this WSGI file, you can also add ``WSGI_APPLICATION =
  42
+   "mysite.wsgi.application"`` in your settings (replacing ``mysite`` with the
  43
+   name of your project).
  44
+
  45
+Initially this file contains::
  46
+
  47
+    import os
  48
+
  49
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
  50
+
  51
+    # This application object is used by the development server
  52
+    # as well as any WSGI server configured to use this file.
  53
+    from django.core.handlers.wsgi import get_wsgi_application
  54
+    application = get_wsgi_application()
  55
+
  56
+The ``os.environ.setdefault`` line just sets the default settings module to
  57
+use, if you haven't explicitly set the :envvar:`DJANGO_SETTINGS_MODULE`
  58
+environment variable. You'll need to edit this line to replace ``mysite`` with
  59
+the name of your project package, so the path to your settings module is
  60
+correct.
  61
+
  62
+To apply `WSGI middleware`_ you can simply wrap the application object
  63
+in the same file::
  64
+
  65
+    from helloworld.wsgi import HelloWorldApplication
  66
+    application = HelloWorldApplication(application)
  67
+
  68
+You could also replace the Django WSGI application with a custom WSGI
  69
+application that later delegates to the Django WSGI application, if you want to
  70
+combine a Django application with a WSGI application of another framework.
  71
+
  72
+.. _`WSGI middleware`: http://www.python.org/dev/peps/pep-3333/#middleware-components-that-play-both-sides
175  docs/howto/deployment/wsgi/modwsgi.txt
... ...
@@ -0,0 +1,175 @@
  1
+==========================================
  2
+How to use Django with Apache and mod_wsgi
  3
+==========================================
  4
+
  5
+Deploying Django with Apache_ and `mod_wsgi`_ is a tried and tested way to get
  6
+Django into production.
  7
+
  8
+.. _Apache: http://httpd.apache.org/
  9
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
  10
+
  11
+mod_wsgi is an Apache module which can host any Python WSGI_ application,
  12
+including Django. Django will work with any version of Apache which supports
  13
+mod_wsgi.
  14
+
  15
+.. _WSGI: http://www.wsgi.org
  16
+
  17
+The `official mod_wsgi documentation`_ is fantastic; it's your source for all
  18
+the details about how to use mod_wsgi. You'll probably want to start with the
  19
+`installation and configuration documentation`_.
  20
+
  21
+.. _official mod_wsgi documentation: http://www.modwsgi.org/
  22
+.. _installation and configuration documentation: http://www.modwsgi.org/wiki/InstallationInstructions
  23
+
  24
+Basic configuration
  25
+===================
  26
+
  27
+Once you've got mod_wsgi installed and activated, edit your Apache server's
  28
+``httpd.conf`` file and add::
  29
+
  30
+    WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
  31
+    WSGIPythonPath /path/to/mysite.com
  32
+
  33
+    <Directory /path/to/mysite.com/mysite>
  34
+    <Files wsgi.py>
  35
+    Order deny,allow
  36
+    Allow from all
  37
+    </Files>
  38
+    </Directory>
  39
+
  40
+The first bit in the ``WSGIScriptAlias`` line is the base URL path you want to
  41
+serve your application at (``/`` indicates the root url), and the second is the
  42
+location of a "WSGI file" -- see below -- on your system, usually inside of
  43
+your project package (``mysite`` in this example). This tells Apache to serve
  44
+any request below the given URL using the WSGI application defined in that
  45
+file.
  46
+
  47
+The ``WSGIPythonPath`` line ensures that your project package is available for
  48
+import on the Python path; in other words, that ``import mysite`` works.
  49
+
  50
+The ``<Directory>`` piece just ensures that Apache can access your
  51
+:file:`wsgi.py` file.
  52
+
  53
+Next we'll need to ensure this :file:`wsgi.py` with a WSGI application object
  54
+exists. As of Django version 1.4, :djadmin:`startproject` will have created one
  55
+for you; otherwise, you'll need to create it. See the :doc:`WSGI overview
  56
+documentation</howto/deployment/wsgi/index>` for the default contents you
  57
+should put in this file, and what else you can add to it.
  58
+
  59
+Using a virtualenv
  60
+==================
  61
+
  62
+If you install your project's Python dependencies inside a `virtualenv`_,
  63
+you'll need to add the path to this virtualenv's ``site-packages`` directory to
  64
+your Python path as well. To do this, you can add another line to your
  65
+Apache configuration::
  66
+
  67
+    WSGIPythonPath /path/to/your/venv/lib/python2.X/site-packages
  68
+
  69
+Make sure you give the correct path to your virtualenv, and replace
  70
+``python2.X`` with the correct Python version (e.g. ``python2.7``).
  71
+
  72
+.. _virtualenv: http://www.virtualenv.org
  73
+
  74
+Using mod_wsgi daemon mode
  75
+==========================
  76
+
  77
+"Daemon mode" is the recommended mode for running mod_wsgi (on non-Windows
  78
+platforms). See the `official mod_wsgi documentation`_ for details on setting
  79
+up daemon mode. The only change required to the above configuration if you use
  80
+daemon mode is that you can't use ``WSGIPythonPath``; instead you should use
  81
+the ``python-path`` option to ``WSGIDaemonProcess``, for example::
  82
+
  83
+    WSGIDaemonProcess example.com python-path=/path/to/mysite.com:/path/to/venv/lib/python2.7/site-packages
  84
+
  85
+.. _serving-files:
  86
+
  87
+Serving files
  88
+=============
  89
+
  90
+Django doesn't serve files itself; it leaves that job to whichever Web
  91
+server you choose.
  92
+
  93
+We recommend using a separate Web server -- i.e., one that's not also running
  94
+Django -- for serving media. Here are some good choices:
  95
+
  96
+* lighttpd_
  97
+* Nginx_
  98
+* TUX_
  99
+* A stripped-down version of Apache_
  100
+* Cherokee_
  101
+
  102
+If, however, you have no option but to serve media files on the same Apache
  103
+``VirtualHost`` as Django, you can set up Apache to serve some URLs as
  104
+static media, and others using the mod_wsgi interface to Django.
  105
+
  106
+This example sets up Django at the site root, but explicitly serves
  107
+``robots.txt``, ``favicon.ico``, any CSS file, and anything in the
  108
+``/static/`` and ``/media/`` URL space as a static file. All other URLs
  109
+will be served using mod_wsgi::
  110
+
  111
+    Alias /robots.txt /path/to/mysite.com/static/robots.txt
  112
+    Alias /favicon.ico /path/to/mysite.com/static/favicon.ico
  113
+
  114
+    AliasMatch ^/([^/]*\.css) /path/to/mysite.com/static/styles/$1
  115
+
  116
+    Alias /media/ /path/to/mysite.com/media/
  117
+    Alias /static/ /path/to/mysite.com/static/
  118
+
  119
+    <Directory /path/to/mysite.com/static>
  120
+    Order deny,allow
  121
+    Allow from all
  122
+    </Directory>
  123
+
  124
+    <Directory /path/to/mysite.com/media>
  125
+    Order deny,allow
  126
+    Allow from all
  127
+    </Directory>
  128
+
  129
+    WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
  130
+
  131
+    <Directory /path/to/mysite.com/mysite>
  132
+    <Files wsgi.py>
  133
+    Order allow,deny
  134
+    Allow from all
  135
+    </Files>
  136
+    </Directory>
  137
+
  138
+.. _lighttpd: http://www.lighttpd.net/
  139
+.. _Nginx: http://wiki.nginx.org/Main
  140
+.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
  141
+.. _Apache: http://httpd.apache.org/
  142
+.. _Cherokee: http://www.cherokee-project.com/
  143
+
  144
+.. More details on configuring a mod_wsgi site to serve static files can be found
  145
+.. in the mod_wsgi documentation on `hosting static files`_.
  146
+
  147
+.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files
  148
+
  149
+.. _serving-the-admin-files:
  150
+
  151
+Serving the admin files
  152
+=======================
  153
+
  154
+Note that the Django development server automatically serves the static files
  155
+of the admin app (and any other installed apps), but this is not the case when
  156
+you use any other server arrangement. You're responsible for setting up Apache,
  157
+or whichever media server you're using, to serve the admin files.
  158
+
  159
+The admin files live in (:file:`django/contrib/admin/static/admin`) of the
  160
+Django distribution.
  161
+
  162
+We **strongly** recommend using :mod:`django.contrib.staticfiles` (along with
  163
+a Web server as outlined in the previous section) to handle the admin files, but
  164
+here are three other approaches:
  165
+
  166
+1. Create a symbolic link to the admin static files from within your
  167
+   document root (this may require ``+FollowSymLinks`` in your Apache
  168
+   configuration).
  169
+
  170
+2. Use an ``Alias`` directive, as demonstrated above, to alias the appropriate
  171
+   URL (probably :setting:`STATIC_URL` + `admin/`) to the actual location of
  172
+   the admin files.
  173
+
  174
+3. Copy the admin static files so that they live within your Apache
  175
+   document root.
52  docs/howto/deployment/uwsgi.txt → docs/howto/deployment/wsgi/uwsgi.txt
@@ -36,7 +36,7 @@ uWSGI model
36 36
 -----------
37 37
 
38 38
 uWSGI operates on a client-server model. Your Web server (ie. nginx, Apache)
39  
-communicates with a django-uwsgi "worker" process to serve dynamic contents.
  39
+communicates with a django-uwsgi "worker" process to serve dynamic content.
40 40
 The Web server can communicate with the uWSGI process either:
41 41
 
42 42
 * 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
48 48
 preference. Usually, a TCP socket is easier because connecting to a port
49 49
 doesn't require special permissions.
50 50
 
51  
-In the second case, the Web server doesn't need to do uWSGI protocol. It just
52  
-needs to be able to proxy HTTP requests to the HTTP server built-in uWSGI.
53  
-The procedure is the same than proxying any HTTP server. Note that the Web
  51
+In the second case, the Web server doesn't need to speak the uWSGI protocol. It
  52
+just needs to be able to proxy HTTP requests to the HTTP server built-in uWSGI.
  53
+The procedure is the same as proxying to any HTTP server. Note that the Web
54 54
 server is a "reverse proxy" in this case.
55 55
 
56 56
 Configuring the uWSGI server
@@ -68,9 +68,9 @@ the uWSGI server.
68 68
     on that file.
69 69
 
70 70
 uWSGI is highly configurable and thus there are many ways to start the
71  
-process. For example, uwsgi version 0.9.6.8 provides a hundred switches.
72  
-This guide demonstrates the most important of them, but does not intent to
73  
-substitute the official manual and online documentation.
  71
+process. For example, uwsgi version 0.9.6.8 provides a hundred switches.  This
  72
+guide demonstrates the most important of them, but is not a substitute the
  73
+official manual and online documentation.
74 74
 
75 75
 uWSGI supports configuration through:
76 76
 
@@ -98,8 +98,8 @@ uWSGI server. This means:
98 98
 
99 99
 * the uWSGI server can be restarted or reloaded independently from the Web
100 100
   server,
101  
-* (except with Cheerokee), it is the role of the system administrator to make
102  
-  uWSGI to start on boot or reboot: either through tools like supervisor or
  101
+* (except with Cherokee), it is the role of the system administrator to make
  102
+  uWSGI start on boot or reboot: either through tools like supervisor or
103 103
   daemontools, either directly at init level in a file like /etc/rc.local or
104 104
   /etc/conf.d/local
105 105
 
@@ -109,11 +109,11 @@ Managing uWSGI
109 109
 Starting the server
110 110
 -------------------
111 111
 
112  
-Example command line for a Web server that understand the uWSGI protocol::
  112
+Example command line for a Web server that understands the uWSGI protocol::
113 113
 
114 114
     uwsgi --chdir=/path/to/your/project
115  
-        --module='django.core.handlers.wsgi:WSGIHandler()' \
116  
-        --env DJANGO_SETTINGS_MODULE=settings \
  115
+        --module='mysite.wsgi:application' \
  116
+        --env DJANGO_SETTINGS_MODULE=mysite.settings \
117 117
         --master --pidfile=/tmp/project-master.pid \
118 118
         --socket=127.0.0.1:49152 \      # can also be a file
119 119
         --processes=5 \                 # number of worker processes
@@ -125,17 +125,27 @@ Example command line for a Web server that understand the uWSGI protocol::
125 125
         --home=/path/to/virtual/env \   # optionnal path to a virtualenv
126 126
         --daemonize=/var/log/uwsgi/yourproject.log      # background the process
127 127
 
128  
-Django specific options are:
  128
+This assumes that you have a top-level project package named ``mysite``, and
  129
+within it a module :file:`mysite/wsgi.py` that contains a WSGI ``application``
  130
+object. This is the layout you will have if you ran ``django-admin.py
  131
+startproject mysite`` (using your own project name in place of ``mysite``) with
  132
+a recent version of Django. If this file does not exist, you'll need to create
  133
+it. See the :doc:`/howto/deployment/wsgi/index` documentation for the default
  134
+contents you should put in this file, and what else you can add to it.
129 135
 
130  
-* ``chdir``: should be the path to your project
131  
-* ``module``: uwsgi module to use
132  
-* ``pythonpath``: optional path to your project virtualenv
133  
-* ``env``: should contain at least ``DJANGO_SETTINGS_MODULE``
  136
+The Django-specific options here are:
  137
+
  138
+* ``chdir``: the path to the directory that needs to be on Python's import path; i.e. the directory containing the ``mysite`` package.
  139
+* ``module``: The WSGI module to use, probably the ``mysite.wsgi`` module which
  140
+  :djadmin:`startproject` creates.
  141
+* ``env``: should probably contain at least ``DJANGO_SETTINGS_MODULE``
  142
+* ``home``: optional path to your project virtualenv
134 143
 
135 144
 Example ini configuration file::
136 145
 
137 146
     [uwsgi]
138 147
     chdir=/path/to/your/project
  148
+    module='mysite.wsgi:application'
139 149
     master=True
140 150
     pidfile=/tmp/project-master.pid
141 151
     vacuum=True
@@ -157,7 +167,7 @@ Read more `uWSGI configuration examples
157 167
 Reloading the daemon
158 168
 --------------------
159 169
 
160  
-As mentioned above, the uWSGI master process is one of the core component of
  170
+As mentioned above, the uWSGI master process is one of the core components of
161 171
 the uWSGI stack. The signal to brutally reload all the workers and the master
162 172
 process is SIGTERM. Example command to brutally reload the uWSGI processes::
163 173
 
@@ -167,7 +177,7 @@ Patching the daemon
167 177
 -------------------
168 178
 
169 179
 One of the great advantages of uWSGI is its ability to gradually restart each
170  
-worker without loosing any request.
  180
+worker without losing any requests.
171 181
 
172 182
 For example, uWSGI can be signaled that worker should reload the code after
173 183
 handling their current request (if any) from bash::
@@ -236,7 +246,7 @@ still experimental.
236 246
 Troubleshooting
237 247
 ===============
238 248
 
239  
-As usual, the first things to do is to check the logs. This implies:
  249
+As usual, the first thing to do is to check the logs. This implies:
240 250
 
241 251
 * the web server log, which will indicate if it couldn't connect to the uWSGI
242 252
   process,
@@ -251,5 +261,5 @@ Typical gotchas:
251 261
   killed with ``SIGKILL``, it won't remove the socket and pidfile when it is
252 262
   interrupted. It is safe to remove them manually and to start uWSGI again in
253 263
   that case.
254  
-* uWSGI can start the process on the foreground, this will make errors easily
  264
+* uWSGI can start the process in the foreground, this will make errors easily
255 265
   visible to the system administrator.
5  docs/index.txt
@@ -154,10 +154,9 @@ The development process
154 154
 
155 155
 * **Deployment:**
156 156
   :doc:`Overview <howto/deployment/index>` |
157  
-  :doc:`Apache/mod_wsgi <howto/deployment/modwsgi>` |
158  
-  :doc:`uWSGI <howto/deployment/uwsgi>` |
159  
-  :doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
  157
+  :doc:`WSGI servers <howto/deployment/wsgi/index>` |
160 158
   :doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` |
  159
+  :doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
161 160
   :doc:`Apache authentication <howto/apache-auth>` |
162 161
   :doc:`Handling static files <howto/static-files>` |
163 162
   :doc:`Tracking code errors by email <howto/error-reporting>`
4  docs/intro/tutorial01.txt
@@ -95,6 +95,7 @@ Let's look at what :djadmin:`startproject` created::
95 95
             __init__.py
96 96
             settings.py
97 97
             urls.py
  98
+            wsgi.py
98 99
 
99 100
 .. admonition:: Doesn't match what you see?
100 101
 
@@ -129,6 +130,9 @@ These files are:
129 130
   "table of contents" of your Django-powered site. You can read more about
130 131
   URLs in :doc:`/topics/http/urls`.
131 132
 
  133
+* :file:`mysite/wsgi.py`: An entry-point for WSGI-compatible webservers to
  134
+  serve your project. See :doc:`/howto/deployment/wsgi/index` for more details.
  135
+
132 136
 .. _more about packages: http://docs.python.org/tutorial/modules.html#packages
133 137
 
134 138
 The development server
6  docs/ref/contrib/gis/deployment.txt
@@ -54,7 +54,7 @@ Example::
54 54
     number of ``processes`` instead.
55 55
 
56 56
 For more information, please consult Django's
57  
-:doc:`mod_wsgi documentation </howto/deployment/modwsgi>`.
  57
+:doc:`mod_wsgi documentation </howto/deployment/wsgi/modwsgi>`.
58 58
 
59 59
 ``mod_python``
60 60
 --------------
@@ -62,8 +62,8 @@ For more information, please consult Django's
62 62
 .. warning::
63 63
     Support for mod_python will be deprecated in a future release of Django. If
64 64
     you are configuring a new deployment, you are strongly encouraged to
65  
-    consider using :doc:`mod_wsgi </howto/deployment/modwsgi>` or any of the
66  
-    other :doc:`supported backends </howto/deployment/index>`.
  65
+    consider using :doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` or any of
  66
+    the other :doc:`supported servers </howto/deployment/index>`.
67 67
 
68 68
 Example::
69 69
 
8  docs/ref/django-admin.txt
@@ -504,6 +504,10 @@ supports the FastCGI protocol. See the :doc:`FastCGI deployment documentation
504 504
 </howto/deployment/fastcgi>` for details. Requires the Python FastCGI module from
505 505
 `flup`_.
506 506
 
  507
+.. versionadded:: 1.4
  508
+    Internally, this wraps the WSGI application object specified by the
  509
+    :setting:`WSGI_APPLICATION` setting.
  510
+
507 511
 .. _flup: http://www.saddi.com/software/flup/
508 512
 
509 513
 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
628 632
 might not have access to start a port on a low port number. Low port numbers
629 633
 are reserved for the superuser (root).
630 634
 
  635
+.. versionadded:: 1.4
  636
+    This server uses the WSGI application object specified by the
  637
+    :setting:`WSGI_APPLICATION` setting.
  638
+
631 639
 DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through
632 640
 security audits or performance tests. (And that's how it's gonna stay. We're in
633 641
 the business of making Web frameworks, not Web servers, so improving this
19  docs/ref/settings.txt
@@ -2095,6 +2095,25 @@ A boolean that specifies whether to use the X-Forwarded-Host header in
2095 2095
 preference to the Host header. This should only be enabled if a proxy
2096 2096
 which sets this header is in use.
2097 2097
 
  2098
+.. setting:: WSGI_APPLICATION
  2099
+
  2100
+WSGI_APPLICATION
  2101
+----------------
  2102
+
  2103
+.. versionadded:: 1.4
  2104
+
  2105
+Default: ``None``
  2106
+
  2107
+The full Python path of the WSGI application object that Django's built-in
  2108
+servers (e.g. :djadmin:`runserver`) will use. The :djadmin:`django-admin.py
  2109
+startproject <startproject>` management command will create a simple
  2110
+``wsgi.py`` file with an ``application`` callable in it, and point this setting
  2111
+to that ``application``.
  2112
+
  2113
+If not set, the return value of :func:`django.core.wsgi.get_wsgi_application`
  2114
+will be used. In this case, the behavior of :djadmin:`runserver` will be
  2115
+identical to previous Django versions.
  2116
+
2098 2117
 .. setting:: YEAR_MONTH_FORMAT
2099 2118
 
2100 2119
 YEAR_MONTH_FORMAT
2  docs/releases/1.3-alpha-1.txt
@@ -303,7 +303,7 @@ more flexible ``mod_wsgi`` backend.
303 303
 
304 304
 If you are currently using the ``mod_python`` request handler, you are strongly
305 305
 encouraged to redeploy your Django instances using :doc:`mod_wsgi
306  
-</howto/deployment/modwsgi>`.
  306
+</howto/deployment/wsgi/modwsgi>`.
307 307
 
308 308
 Function-based generic views
309 309
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  docs/releases/1.3.txt
@@ -688,7 +688,7 @@ more flexible ``mod_wsgi`` backend.
688 688
 
689 689
 If you are currently using the ``mod_python`` request handler, you
690 690
 should redeploy your Django projects using another request handler.
691  
-:doc:`mod_wsgi </howto/deployment/modwsgi>` is the request handler
  691
+:doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` is the request handler
692 692
 recommended by the Django project, but :doc:`FastCGI
693 693
 </howto/deployment/fastcgi>` is also supported. Support for
694 694
 ``mod_python`` deployment will be removed in Django 1.5.
18  docs/releases/1.4.txt
@@ -403,6 +403,24 @@ prefix, some places without it), the imports will need to be cleaned up when
403 403
 switching to the new ``manage.py``.
404 404
 
405 405
 
  406
+Improved WSGI support
  407
+~~~~~~~~~~~~~~~~~~~~~
  408
+
  409
+The :djadmin:`startproject` management command now adds a :file:`wsgi.py`
  410
+module to the initial project layout, containing a simple WSGI application that
  411
+can be used for :doc:`deploying with WSGI app
  412
+servers</howto/deployment/wsgi/index>`.
  413
+
  414
+The :djadmin:`built-in development server<runserver>` now supports using an
  415
+externally-defined WSGI callable, so as to make it possible to run runserver
  416
+with the same WSGI configuration that is used for deployment. A new
  417
+:setting:`WSGI_APPLICATION` setting is available to configure which WSGI
  418
+callable :djadmin:`runserver` uses.
  419
+
  420
+(The :djadmin:`runfcgi` management command also internally wraps the WSGI