Ticket #18029: 18029-1.diff

File 18029-1.diff, 46.8 KB (added by Claude Paroz, 12 years ago)

modpython removal

  • deleted file django/contrib/auth/handlers/modpython.py

    diff --git a/django/contrib/auth/handlers/__init__.py b/django/contrib/auth/handlers/__init__.py
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/django/contrib/auth/handlers/modpython.py b/django/contrib/auth/handlers/modpython.py
    deleted file mode 100644
    index de961fa..0000000
    + -  
    1 from mod_python import apache
    2 import os
    3 
    4 def authenhandler(req, **kwargs):
    5     """
    6     Authentication handler that checks against Django's auth database.
    7     """
    8 
    9     # mod_python fakes the environ, and thus doesn't process SetEnv.  This fixes
    10     # that so that the following import works
    11     os.environ.update(req.subprocess_env)
    12 
    13     # apache 2.2 requires a call to req.get_basic_auth_pw() before
    14     # req.user and friends are available.
    15     req.get_basic_auth_pw()
    16 
    17     # check for PythonOptions
    18     _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
    19 
    20     options = req.get_options()
    21     permission_name = options.get('DjangoPermissionName', None)
    22     staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
    23     superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
    24     settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
    25     if settings_module:
    26         os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
    27 
    28     from django.contrib.auth.models import User
    29     from django import db
    30     db.reset_queries()
    31 
    32     # check that the username is valid
    33     kwargs = {'username': req.user, 'is_active': True}
    34     if staff_only:
    35         kwargs['is_staff'] = True
    36     if superuser_only:
    37         kwargs['is_superuser'] = True
    38     try:
    39         try:
    40             user = User.objects.get(**kwargs)
    41         except User.DoesNotExist:
    42             return apache.HTTP_UNAUTHORIZED
    43    
    44         # check the password and any permission given
    45         if user.check_password(req.get_basic_auth_pw()):
    46             if permission_name:
    47                 if user.has_perm(permission_name):
    48                     return apache.OK
    49                 else:
    50                     return apache.HTTP_UNAUTHORIZED
    51             else:
    52                 return apache.OK
    53         else:
    54             return apache.HTTP_UNAUTHORIZED
    55     finally:
    56         db.connection.close()
  • django/core/cache/__init__.py

    diff --git a/django/core/cache/__init__.py b/django/core/cache/__init__.py
    index 9eac8ec..d8095d4 100644
    a b cache class.  
    1414
    1515See docs/topics/cache.txt for information on the public API.
    1616"""
     17from urlparse import parse_qsl
     18
    1719from django.conf import settings
    1820from django.core import signals
    1921from django.core.cache.backends.base import (
    from django.core.cache.backends.base import (  
    2123from django.core.exceptions import ImproperlyConfigured
    2224from django.utils import importlib
    2325
    24 try:
    25     # The mod_python version is more efficient, so try importing it first.
    26     from mod_python.util import parse_qsl
    27 except ImportError:
    28     from urlparse import parse_qsl
    29 
    3026__all__ = [
    3127    'get_cache', 'cache', 'DEFAULT_CACHE_ALIAS'
    3228]
  • deleted file django/core/handlers/modpython.py

    diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
    deleted file mode 100644
    index fb23fb4..0000000
    + -  
    1 import os
    2 import sys
    3 from warnings import warn
    4 
    5 from django import http
    6 from django.core import signals
    7 from django.core.handlers.base import BaseHandler
    8 from django.core.urlresolvers import set_script_prefix
    9 from django.utils import datastructures
    10 from django.utils.encoding import force_unicode, iri_to_uri
    11 from django.utils.log import getLogger
    12 
    13 logger = getLogger('django.request')
    14 
    15 class ModPythonRequest(http.HttpRequest):
    16     def __init__(self, req):
    17         self._req = req
    18         # FIXME: This isn't ideal. The request URI may be encoded (it's
    19         # non-normalized) slightly differently to the "real" SCRIPT_NAME
    20         # and PATH_INFO values. This causes problems when we compute path_info,
    21         # below. For now, don't use script names that will be subject to
    22         # encoding/decoding.
    23         self.path = force_unicode(req.uri)
    24         root = req.get_options().get('django.root', '')
    25         self.django_root = root
    26         # req.path_info isn't necessarily computed correctly in all
    27         # circumstances (it's out of mod_python's control a bit), so we use
    28         # req.uri and some string manipulations to get the right value.
    29         if root and req.uri.startswith(root):
    30             self.path_info = force_unicode(req.uri[len(root):])
    31         else:
    32             self.path_info = self.path
    33         if not self.path_info:
    34             # Django prefers empty paths to be '/', rather than '', to give us
    35             # a common start character for URL patterns. So this is a little
    36             # naughty, but also pretty harmless.
    37             self.path_info = u'/'
    38         self._post_parse_error = False
    39         self._stream = self._req
    40         self._read_started = False
    41 
    42     def get_full_path(self):
    43         # RFC 3986 requires self._req.args to be in the ASCII range, but this
    44         # doesn't always happen, so rather than crash, we defensively encode it.
    45         return '%s%s' % (self.path, self._req.args and ('?' + iri_to_uri(self._req.args)) or '')
    46 
    47     def _is_secure(self):
    48         try:
    49             return self._req.is_https()
    50         except AttributeError:
    51             # mod_python < 3.2.10 doesn't have req.is_https().
    52             return self._req.subprocess_env.get('HTTPS', '').lower() in ('on', '1')
    53 
    54     def _get_request(self):
    55         if not hasattr(self, '_request'):
    56             self._request = datastructures.MergeDict(self.POST, self.GET)
    57         return self._request
    58 
    59     def _get_get(self):
    60         if not hasattr(self, '_get'):
    61             self._get = http.QueryDict(self._req.args, encoding=self._encoding)
    62         return self._get
    63 
    64     def _set_get(self, get):
    65         self._get = get
    66 
    67     def _get_post(self):
    68         if not hasattr(self, '_post'):
    69             self._load_post_and_files()
    70         return self._post
    71 
    72     def _set_post(self, post):
    73         self._post = post
    74 
    75     def _get_cookies(self):
    76         if not hasattr(self, '_cookies'):
    77             self._cookies = http.parse_cookie(self._req.headers_in.get('cookie', ''))
    78         return self._cookies
    79 
    80     def _set_cookies(self, cookies):
    81         self._cookies = cookies
    82 
    83     def _get_files(self):
    84         if not hasattr(self, '_files'):
    85             self._load_post_and_files()
    86         return self._files
    87 
    88     def _get_meta(self):
    89         "Lazy loader that returns self.META dictionary"
    90         if not hasattr(self, '_meta'):
    91             self._meta = {
    92                 'AUTH_TYPE':         self._req.ap_auth_type,
    93                 'CONTENT_LENGTH':    self._req.headers_in.get('content-length', 0),
    94                 'CONTENT_TYPE':      self._req.headers_in.get('content-type'),
    95                 'GATEWAY_INTERFACE': 'CGI/1.1',
    96                 'PATH_INFO':         self.path_info,
    97                 'PATH_TRANSLATED':   None, # Not supported
    98                 'QUERY_STRING':      self._req.args,
    99                 'REMOTE_ADDR':       self._req.connection.remote_ip,
    100                 'REMOTE_HOST':       None, # DNS lookups not supported
    101                 'REMOTE_IDENT':      self._req.connection.remote_logname,
    102                 'REMOTE_USER':       self._req.user,
    103                 'REQUEST_METHOD':    self._req.method,
    104                 'SCRIPT_NAME':       self.django_root,
    105                 'SERVER_NAME':       self._req.server.server_hostname,
    106                 'SERVER_PORT':       self._req.connection.local_addr[1],
    107                 'SERVER_PROTOCOL':   self._req.protocol,
    108                 'SERVER_SOFTWARE':   'mod_python'
    109             }
    110             for key, value in self._req.headers_in.items():
    111                 key = 'HTTP_' + key.upper().replace('-', '_')
    112                 self._meta[key] = value
    113         return self._meta
    114 
    115     def _get_method(self):
    116         return self.META['REQUEST_METHOD'].upper()
    117 
    118     GET = property(_get_get, _set_get)
    119     POST = property(_get_post, _set_post)
    120     COOKIES = property(_get_cookies, _set_cookies)
    121     FILES = property(_get_files)
    122     META = property(_get_meta)
    123     REQUEST = property(_get_request)
    124     method = property(_get_method)
    125 
    126 class ModPythonHandler(BaseHandler):
    127     request_class = ModPythonRequest
    128 
    129     def __call__(self, req):
    130         warn(('The mod_python handler is deprecated; use a WSGI or FastCGI server instead.'),
    131              DeprecationWarning)
    132 
    133         # mod_python fakes the environ, and thus doesn't process SetEnv.  This fixes that
    134         os.environ.update(req.subprocess_env)
    135 
    136         # now that the environ works we can see the correct settings, so imports
    137         # that use settings now can work
    138         from django.conf import settings
    139 
    140         # if we need to set up middleware, now that settings works we can do it now.
    141         if self._request_middleware is None:
    142             self.load_middleware()
    143 
    144         set_script_prefix(req.get_options().get('django.root', ''))
    145         signals.request_started.send(sender=self.__class__)
    146         try:
    147             try:
    148                 request = self.request_class(req)
    149             except UnicodeDecodeError:
    150                 logger.warning('Bad Request (UnicodeDecodeError)',
    151                     exc_info=sys.exc_info(),
    152                     extra={
    153                         'status_code': 400,
    154                     }
    155                 )
    156                 response = http.HttpResponseBadRequest()
    157             else:
    158                 response = self.get_response(request)
    159         finally:
    160             signals.request_finished.send(sender=self.__class__)
    161 
    162         # Convert our custom HttpResponse object back into the mod_python req.
    163         req.content_type = response['Content-Type']
    164         for key, value in response.items():
    165             if key != 'content-type':
    166                 req.headers_out[str(key)] = str(value)
    167         for c in response.cookies.values():
    168             req.headers_out.add('Set-Cookie', c.output(header=''))
    169         req.status = response.status_code
    170         try:
    171             for chunk in response:
    172                 req.write(chunk)
    173         finally:
    174             response.close()
    175 
    176         return 0 # mod_python.apache.OK
    177 
    178 def handler(req):
    179     # mod_python hooks into this function.
    180     return ModPythonHandler()(req)
  • deleted file django/core/handlers/profiler-hotshot.py

    diff --git a/django/core/handlers/profiler-hotshot.py b/django/core/handlers/profiler-hotshot.py
    deleted file mode 100644
    index 0522de6..0000000
    + -  
    1 import hotshot
    2 import os
    3 import time
    4 
    5 from django.core.handlers.modpython import ModPythonHandler
    6 
    7 PROFILE_DATA_DIR = "/var/log/cmsprofile"
    8 
    9 def handler(req):
    10     '''
    11     Handler that uses hotshot to store profile data.
    12 
    13     Stores profile data in PROFILE_DATA_DIR.  Since hotshot has no way (that I
    14     know of) to append profile data to a single file, each request gets its own
    15     profile.  The file names are in the format <url>.<n>.prof where <url> is
    16     the request path with "/" replaced by ".", and <n> is a timestamp with
    17     microseconds to prevent overwriting files.
    18 
    19     Use the gather_profile_stats.py script to gather these individual request
    20     profiles into aggregated profiles by request path.
    21     '''
    22     profname = "%s.%.3f.prof" % (req.uri.strip("/").replace('/', '.'), time.time())
    23     profname = os.path.join(PROFILE_DATA_DIR, profname)
    24     prof = hotshot.Profile(profname)
    25     return prof.runcall(ModPythonHandler(), req)
  • django/http/__init__.py

    diff --git a/django/http/__init__.py b/django/http/__init__.py
    index 5f407a4..2f3392f 100644
    a b import warnings  
    99
    1010from pprint import pformat
    1111from urllib import urlencode, quote
    12 from urlparse import urljoin
     12from urlparse import urljoin, parse_qsl
    1313try:
    1414    from cStringIO import StringIO
    1515except ImportError:
    1616    from StringIO import StringIO
    17 try:
    18     # The mod_python version is more efficient, so try importing it first.
    19     from mod_python.util import parse_qsl
    20 except ImportError:
    21     from urlparse import parse_qsl
    2217
    2318import Cookie
    2419# Some versions of Python 2.7 and later won't need this encoding bug fix:
    class HttpRequest(object):  
    348343    ## File-like and iterator interface.
    349344    ##
    350345    ## Expects self._stream to be set to an appropriate source of bytes by
    351     ## a corresponding request subclass (WSGIRequest or ModPythonRequest).
     346    ## a corresponding request subclass (e.g. WSGIRequest).
    352347    ## Also when request data has already been read by request.POST or
    353348    ## request.body, self._stream points to a StringIO instance
    354349    ## containing that data.
  • docs/faq/usage.txt

    diff --git a/docs/faq/usage.txt b/docs/faq/usage.txt
    index 2b185be..1514543 100644
    a b Make sure that:  
    1313
    1414* The module doesn't contain syntax errors (of course).
    1515
    16 * If you're using mod_python but *not* using Django's request handler,
    17   you'll need to work around a mod_python bug related to the use of
    18   ``SetEnv``; before you import anything from Django you'll need to do
    19   the following::
    20 
    21         os.environ.update(req.subprocess_env)
    22 
    23   (where ``req`` is the mod_python request object).
    24 
    2516I can't stand your template language. Do I have to use it?
    2617----------------------------------------------------------
    2718
  • docs/howto/apache-auth.txt

    diff --git a/docs/howto/apache-auth.txt b/docs/howto/apache-auth.txt
    index 215c519..719fbc1 100644
    a b  
    22Authenticating against Django's user database from Apache
    33=========================================================
    44
    5 .. warning::
    6 
    7     Support for mod_python has been deprecated within Django. At that
    8     time, this method of authentication will no longer be provided by
    9     Django. The community is welcome to offer its own alternate
    10     solutions using WSGI middleware or other approaches.
    11 
    125Since keeping multiple authentication databases in sync is a common problem when
    136dealing with Apache, you can configuring Apache to authenticate against Django's
    14 :doc:`authentication system </topics/auth>` directly. For example, you
    15 could:
     7:doc:`authentication system </topics/auth>` directly. This requires Apache
     8version >= 2.2 and mod_wsgi >= 2.0. For example, you could:
    169
    1710* Serve static/media files directly from Apache only to authenticated users.
    1811
    could:  
    2215* Allow certain users to connect to a WebDAV share created with mod_dav_.
    2316
    2417.. _Subversion: http://subversion.tigris.org/
    25 .. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
     18.. _mod_dav: http://httpd.apache.org/docs/2.2/mod/mod_dav.html
    2619
    2720Configuring Apache
    2821==================
    2922
    3023To check against Django's authorization database from a Apache configuration
    31 file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along
    32 with the standard ``Auth*`` and ``Require`` directives:
     24file, you'll need to set 'wsgi' as the value of ``AuthBasicProvider`` or
     25``AuthDigestProvider`` directive and then use the ``WSGIAuthUserScript``
     26directive to set the path to your authentification script:
    3327
    3428.. code-block:: apache
    3529
    3630    <Location /example/>
    3731        AuthType Basic
    3832        AuthName "example.com"
     33        AuthBasicProvider wsgi
     34        WSGIAuthUserScript /usr/local/wsgi/scripts/auth.wsgi
    3935        Require valid-user
    40 
    41         SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    42         PythonAuthenHandler django.contrib.auth.handlers.modpython
    4336    </Location>
    4437
    45 .. admonition:: Using the authentication handler with Apache 2.2
    46 
    47     If you're using Apache 2.2, you'll need to take a couple extra steps.
    48 
    49     You'll need to ensure that ``mod_auth_basic`` and ``mod_authz_user``
    50     are loaded. These might be compiled statically into Apache, or you might
    51     need to use ``LoadModule`` to load them dynamically (as shown in the
    52     example at the bottom of this note).
    53 
    54     You'll also need to insert configuration directives that prevent Apache
    55     from trying to use other authentication modules, as well as specifying
    56     the ``AuthUserFile`` directive and pointing it to ``/dev/null``. Depending
    57     on which other authentication modules you have loaded, you might need one
    58     or more of the following directives:
    59 
    60     .. code-block:: apache
    61 
    62         AuthBasicAuthoritative Off
    63         AuthDefaultAuthoritative Off
    64         AuthzLDAPAuthoritative Off
    65         AuthzDBMAuthoritative Off
    66         AuthzDefaultAuthoritative Off
    67         AuthzGroupFileAuthoritative Off
    68         AuthzOwnerAuthoritative Off
    69         AuthzUserAuthoritative Off
    70 
    71     A complete configuration, with differences between Apache 2.0 and
    72     Apache 2.2 marked in bold, would look something like:
    73 
    74     .. parsed-literal::
    75 
    76         **LoadModule auth_basic_module modules/mod_auth_basic.so**
    77         **LoadModule authz_user_module modules/mod_authz_user.so**
    78 
    79         ...
    80 
    81         <Location /example/>
    82             AuthType Basic
    83             AuthName "example.com"
    84             **AuthUserFile /dev/null**
    85             **AuthBasicAuthoritative Off**
    86             Require valid-user
    87 
    88             SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    89             PythonAuthenHandler django.contrib.auth.handlers.modpython
    90         </Location>
    91 
    92 By default, the authentication handler will limit access to the ``/example/``
    93 location to users marked as staff members.  You can use a set of
    94 ``PythonOption`` directives to modify this behavior:
    95 
    96 ================================  =========================================
    97 ``PythonOption``                  Explanation
    98 ================================  =========================================
    99 ``DjangoRequireStaffStatus``      If set to ``on`` only "staff" users (i.e.
    100                                   those with the ``is_staff`` flag set)
    101                                   will be allowed.
    102 
    103                                   Defaults to ``on``.
    104 
    105 ``DjangoRequireSuperuserStatus``  If set to ``on`` only superusers (i.e.
    106                                   those with the ``is_superuser`` flag set)
    107                                   will be allowed.
    108 
    109                                   Defaults to ``off``.
    110 
    111 ``DjangoPermissionName``          The name of a permission to require for
    112                                   access. See :ref:`custom permissions
    113                                   <custom-permissions>` for more
    114                                   information.
    115 
    116                                   By default no specific permission will be
    117                                   required.
    118 ================================  =========================================
     38Your auth.wsgi script will have to implement either a
     39``check_password(environ, user, password)`` function (for ``AuthBasicProvider``)
     40or a ``get_realm_hash(environ, user, realm)`` function (for ``AuthDigestProvider``).
    11941
    120 Note that sometimes ``SetEnv`` doesn't play well in this mod_python
    121 configuration, for reasons unknown. If you're having problems getting
    122 mod_python to recognize your ``DJANGO_SETTINGS_MODULE``, you can set it using
    123 ``PythonOption`` instead of ``SetEnv``. Therefore, these two Apache directives
    124 are equivalent::
     42See the `mod_wsgi documentation`_ for more details about the implementation
     43of such a solution.
    12544
    126     SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    127     PythonOption DJANGO_SETTINGS_MODULE mysite.settings
     45.. _mod_wsgi documentation: http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms#Apache_Authentication_Provider
  • docs/howto/deployment/index.txt

    diff --git a/docs/howto/deployment/index.txt b/docs/howto/deployment/index.txt
    index 113f606..8e27a03 100644
    a b ways to easily deploy Django:  
    1111
    1212   wsgi/index
    1313   fastcgi
    14    mod_python (deprecated) <modpython>
    1514
    1615If you're new to deploying Django and/or Python, we'd recommend you try
    1716:doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` first. In most cases it'll be
    the easiest, fastest, and most stable deployment choice.  
    2221    * `Chapter 12 of the Django Book (second edition)`_ discusses deployment
    2322      and especially scaling in more detail. However, note that this edition
    2423      was written against Django version 1.1 and has not been updated since
    25       :doc:`mod_python </howto/deployment/modpython>` was deprecated.
     24      `mod_python` was first deprecated, then completely removed in Django 1.5.
    2625
    2726.. _chapter 12 of the django book (second edition): http://djangobook.com/en/2.0/chapter12/
  • deleted file docs/howto/deployment/modpython.txt

    diff --git a/docs/howto/deployment/modpython.txt b/docs/howto/deployment/modpython.txt
    deleted file mode 100644
    index b1ddf58..0000000
    + -  
    1 ============================================
    2 How to use Django with Apache and mod_python
    3 ============================================
    4 
    5 .. warning::
    6 
    7     Support for mod_python has been deprecated, and will be removed in
    8     Django 1.5. If you are configuring a new deployment, you are
    9     strongly encouraged to consider using :doc:`mod_wsgi
    10     </howto/deployment/wsgi/modwsgi>` or any of the other :doc:`supported
    11     servers </howto/deployment/index>`.
    12 
    13 .. highlight:: apache
    14 
    15 The `mod_python`_ module for Apache_ can be used to deploy Django to a
    16 production server, although it has been mostly superseded by the simpler
    17 :doc:`mod_wsgi deployment option </howto/deployment/wsgi/modwsgi>`.
    18 
    19 mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
    20 Apache and loads Python code into memory when the server starts. Code stays in
    21 memory throughout the life of an Apache process, which leads to significant
    22 performance gains over other server arrangements.
    23 
    24 Django requires Apache 2.x and mod_python 3.x, and you should use Apache's
    25 `prefork MPM`_, as opposed to the `worker MPM`_.
    26 
    27 .. seealso::
    28 
    29     * Apache is a big, complex animal, and this document only scratches the
    30       surface of what Apache can do. If you need more advanced information about
    31       Apache, there's no better source than `Apache's own official
    32       documentation`_
    33 
    34     * You may also be interested in :doc:`How to use Django with FastCGI, SCGI,
    35       or AJP </howto/deployment/fastcgi>`.
    36 
    37 .. _Apache: http://httpd.apache.org/
    38 .. _mod_python: http://www.modpython.org/
    39 .. _mod_perl: http://perl.apache.org/
    40 .. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html
    41 .. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html
    42 .. _apache's own official documentation: http://httpd.apache.org/docs/
    43 
    44 Basic configuration
    45 ===================
    46 
    47 To configure Django with mod_python, first make sure you have Apache installed,
    48 with the mod_python module activated.
    49 
    50 Then edit your ``httpd.conf`` file and add the following::
    51 
    52     <Location "/mysite/">
    53         SetHandler python-program
    54         PythonHandler django.core.handlers.modpython
    55         SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    56         PythonOption django.root /mysite
    57         PythonDebug On
    58     </Location>
    59 
    60 ...and replace ``mysite.settings`` with the Python import path to your Django
    61 project's settings file.
    62 
    63 This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
    64 Django mod_python handler." It passes the value of :ref:`DJANGO_SETTINGS_MODULE
    65 <django-settings-module>` so mod_python knows which settings to use.
    66 
    67 Because mod_python does not know we are serving this site from underneath the
    68 ``/mysite/`` prefix, this value needs to be passed through to the mod_python
    69 handler in Django, via the ``PythonOption django.root ...`` line. The value set
    70 on that line (the last item) should match the string given in the ``<Location
    71 ...>`` directive. The effect of this is that Django will automatically strip the
    72 ``/mysite`` string from the front of any URLs before matching them against your
    73 URLconf patterns. If you later move your site to live under ``/mysite2``, you
    74 will not have to change anything except the ``django.root`` option in the config
    75 file.
    76 
    77 When using ``django.root`` you should make sure that what's left, after the
    78 prefix has been removed, begins with a slash. Your URLconf patterns that are
    79 expecting an initial slash will then work correctly. In the above example,
    80 since we want to send things like ``/mysite/admin/`` to ``/admin/``, we need
    81 to remove the string ``/mysite`` from the beginning, so that is the
    82 ``django.root`` value. It would be an error to use ``/mysite/`` (with a
    83 trailing slash) in this case.
    84 
    85 Note that we're using the ``<Location>`` directive, not the ``<Directory>``
    86 directive. The latter is used for pointing at places on your filesystem,
    87 whereas ``<Location>`` points at places in the URL structure of a Web site.
    88 ``<Directory>`` would be meaningless here.
    89 
    90 Also, if your Django project is not on the default ``PYTHONPATH`` for your
    91 computer, you'll have to tell mod_python where your project can be found:
    92 
    93 .. parsed-literal::
    94 
    95     <Location "/mysite/">
    96         SetHandler python-program
    97         PythonHandler django.core.handlers.modpython
    98         SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    99         PythonOption django.root /mysite
    100         PythonDebug On
    101         **PythonPath "['/path/to/project'] + sys.path"**
    102     </Location>
    103 
    104 The value you use for ``PythonPath`` should include the parent directories of
    105 all the modules you are going to import in your application. It should also
    106 include the parent directory of the :ref:`DJANGO_SETTINGS_MODULE
    107 <django-settings-module>` location. This is exactly the same situation as
    108 setting the Python path for interactive usage. Whenever you try to import
    109 something, Python will run through all the directories in ``sys.path`` in turn,
    110 from first to last, and try to import from each directory until one succeeds.
    111 
    112 Make sure that your Python source files' permissions are set such that the
    113 Apache user (usually named ``apache`` or ``httpd`` on most systems) will have
    114 read access to the files.
    115 
    116 An example might make this clearer. Suppose you have some applications under
    117 ``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/weblog/`` and
    118 so forth), your settings file is at ``/var/www/mysite/settings.py`` and you have
    119 specified :ref:`DJANGO_SETTINGS_MODULE <django-settings-module>` as in the above
    120 example. In this case, you would need to write your ``PythonPath`` directive
    121 as::
    122 
    123     PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"
    124 
    125 With this path, ``import weblog`` and ``import mysite.settings`` will both
    126 work. If you had ``import blogroll`` in your code somewhere and ``blogroll``
    127 lived under the ``weblog/`` directory, you would *also* need to add
    128 ``/usr/local/django-apps/weblog/`` to your ``PythonPath``. Remember: the
    129 **parent directories** of anything you import directly must be on the Python
    130 path.
    131 
    132 .. note::
    133 
    134     If you're using Windows, we still recommended that you use forward
    135     slashes in the pathnames, even though Windows normally uses the backslash
    136     character as its native separator. Apache knows how to convert from the
    137     forward slash format to the native format, so this approach is portable and
    138     easier to read. (It avoids tricky problems with having to double-escape
    139     backslashes.)
    140 
    141     This is valid even on a Windows system::
    142 
    143         PythonPath "['c:/path/to/project'] + sys.path"
    144 
    145 You can also add directives such as ``PythonAutoReload Off`` for performance.
    146 See the `mod_python documentation`_ for a full list of options.
    147 
    148 Note that you should set ``PythonDebug Off`` on a production server. If you
    149 leave ``PythonDebug On``, your users would see ugly (and revealing) Python
    150 tracebacks if something goes wrong within mod_python.
    151 
    152 Restart Apache, and any request to ``/mysite/`` or below will be served by
    153 Django. Note that Django's URLconfs won't trim the "/mysite/" -- they get passed
    154 the full URL.
    155 
    156 When deploying Django sites on mod_python, you'll need to restart Apache each
    157 time you make changes to your Python code.
    158 
    159 .. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html
    160 
    161 Multiple Django installations on the same Apache
    162 ================================================
    163 
    164 It's entirely possible to run multiple Django installations on the same Apache
    165 instance. Just use ``VirtualHost`` for that, like so::
    166 
    167     NameVirtualHost *
    168 
    169     <VirtualHost *>
    170         ServerName www.example.com
    171         # ...
    172         SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    173     </VirtualHost>
    174 
    175     <VirtualHost *>
    176         ServerName www2.example.com
    177         # ...
    178         SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
    179     </VirtualHost>
    180 
    181 If you need to put two Django installations within the same ``VirtualHost``
    182 (or in different ``VirtualHost`` blocks that share the same server name),
    183 you'll need to take a special precaution to ensure mod_python's cache doesn't
    184 mess things up. Use the ``PythonInterpreter`` directive to give different
    185 ``<Location>`` directives separate interpreters::
    186 
    187     <VirtualHost *>
    188         ServerName www.example.com
    189         # ...
    190         <Location "/something">
    191             SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    192             PythonInterpreter mysite
    193         </Location>
    194 
    195         <Location "/otherthing">
    196             SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
    197             PythonInterpreter othersite
    198         </Location>
    199     </VirtualHost>
    200 
    201 The values of ``PythonInterpreter`` don't really matter, as long as they're
    202 different between the two ``Location`` blocks.
    203 
    204 Running a development server with mod_python
    205 ============================================
    206 
    207 If you use mod_python for your development server, you can avoid the hassle of
    208 having to restart the server each time you make code changes. Just set
    209 ``MaxRequestsPerChild 1`` in your ``httpd.conf`` file to force Apache to reload
    210 everything for each request. But don't do that on a production server, or we'll
    211 revoke your Django privileges.
    212 
    213 If you're the type of programmer who debugs using scattered ``print``
    214 statements, note that output to ``stdout`` will not appear in the Apache
    215 log and can even `cause response errors`_.
    216 
    217 .. _cause response errors: http://blog.dscpl.com.au/2009/04/wsgi-and-printing-to-standard-output.html
    218 
    219 If you have the need to print debugging information in a mod_python setup, you
    220 have a few options. You can print to ``stderr`` explicitly, like so::
    221 
    222     print >> sys.stderr, 'debug text'
    223     sys.stderr.flush()
    224 
    225 (note that ``stderr`` is buffered, so calling ``flush`` is necessary if you wish
    226 debugging information to be displayed promptly.)
    227 
    228 A more compact approach is to use an assertion::
    229 
    230     assert False, 'debug text'
    231 
    232 Another alternative is to add debugging information to the template of your page.
    233 
    234 Serving media files
    235 ===================
    236 
    237 Django doesn't serve media files itself; it leaves that job to whichever Web
    238 server you choose.
    239 
    240 We recommend using a separate Web server -- i.e., one that's not also running
    241 Django -- for serving media. Here are some good choices:
    242 
    243 * lighttpd_
    244 * Nginx_
    245 * TUX_
    246 * A stripped-down version of Apache_
    247 * Cherokee_
    248 
    249 If, however, you have no option but to serve media or static files on the
    250 same Apache ``VirtualHost`` as Django, here's how you can turn off mod_python
    251 for a particular part of the site::
    252 
    253     <Location "/media">
    254         SetHandler None
    255     </Location>
    256 
    257 Just change ``Location`` to the root URL of your media files. You can also use
    258 ``<LocationMatch>`` to match a regular expression.
    259 
    260 This example sets up Django at the site root but explicitly disables Django
    261 for the ``media`` and ``static`` subdirectories and any URL that ends with
    262 ``.jpg``, ``.gif`` or ``.png``::
    263 
    264     <Location "/">
    265         SetHandler python-program
    266         PythonHandler django.core.handlers.modpython
    267         SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    268     </Location>
    269 
    270     <Location "/media">
    271         SetHandler None
    272     </Location>
    273 
    274     <Location "/static">
    275         SetHandler None
    276     </Location>
    277 
    278     <LocationMatch "\.(jpg|gif|png)$">
    279         SetHandler None
    280     </LocationMatch>
    281 
    282 .. _lighttpd: http://www.lighttpd.net/
    283 .. _Nginx: http://wiki.nginx.org/Main
    284 .. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
    285 .. _Apache: http://httpd.apache.org/
    286 .. _Cherokee: http://www.cherokee-project.com/
    287 
    288 Serving the admin files
    289 =======================
    290 
    291 Note that the Django development server automagically serves the static files
    292 of the admin app, but this is not the case when you use any other server
    293 arrangement. You're responsible for setting up Apache, or whichever media
    294 server you're using, to serve the admin files.
    295 
    296 The admin files live in (:file:`django/contrib/admin/static/admin`) of the
    297 Django distribution.
    298 
    299 We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle the
    300 admin files (this means using the :djadmin:`collectstatic` management command
    301 to collect the static files in :setting:`STATIC_ROOT`, and then configuring
    302 your Web server to serve :setting:`STATIC_ROOT` at :setting:`STATIC_URL`), but
    303 here are two other approaches:
    304 
    305 1. Create a symbolic link to the admin static files from within your
    306    document root.
    307 
    308 2. Or, copy the admin static files so that they live within your Apache
    309    document root.
    310 
    311 Using "eggs" with mod_python
    312 ============================
    313 
    314 If you installed Django from a Python egg_ or are using eggs in your Django
    315 project, some extra configuration is required. Create an extra file in your
    316 project (or somewhere else) that contains something like the following:
    317 
    318 .. code-block:: python
    319 
    320     import os
    321     os.environ['PYTHON_EGG_CACHE'] = '/some/directory'
    322 
    323 Here, ``/some/directory`` is a directory that the Apache Web server process can
    324 write to. It will be used as the location for any unpacking of code the eggs
    325 need to do.
    326 
    327 Then you have to tell mod_python to import this file before doing anything
    328 else. This is done using the PythonImport_ directive to mod_python. You need
    329 to ensure that you have specified the ``PythonInterpreter`` directive to
    330 mod_python as described above__ (you need to do this even if you aren't
    331 serving multiple installations in this case). Then add the ``PythonImport``
    332 line in the main server configuration (i.e., outside the ``Location`` or
    333 ``VirtualHost`` sections). For example::
    334 
    335     PythonInterpreter my_django
    336     PythonImport /path/to/my/project/file.py my_django
    337 
    338 Note that you can use an absolute path here (or a normal dotted import path),
    339 as described in the `mod_python manual`_. We use an absolute path in the
    340 above example because if any Python path modifications are required to access
    341 your project, they will not have been done at the time the ``PythonImport``
    342 line is processed.
    343 
    344 .. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs
    345 .. _PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html
    346 .. _mod_python manual: PythonImport_
    347 __ `Multiple Django installations on the same Apache`_
    348 
    349 Error handling
    350 ==============
    351 
    352 When you use Apache/mod_python, errors will be caught by Django -- in other
    353 words, they won't propagate to the Apache level and won't appear in the Apache
    354 ``error_log``.
    355 
    356 The exception for this is if something is really wonky in your Django setup. In
    357 that case, you'll see an "Internal Server Error" page in your browser and the
    358 full Python traceback in your Apache ``error_log`` file. The ``error_log``
    359 traceback is spread over multiple lines. (Yes, this is ugly and rather hard to
    360 read, but it's how mod_python does things.)
    361 
    362 If you get a segmentation fault
    363 ===============================
    364 
    365 If Apache causes a segmentation fault, there are two probable causes, neither
    366 of which has to do with Django itself.
    367 
    368 1. It may be because your Python code is importing the "pyexpat" module,
    369    which may conflict with the version embedded in Apache. For full
    370    information, see `Expat Causing Apache Crash`_.
    371 
    372 2. It may be because you're running mod_python and mod_php in the same
    373    Apache instance, with MySQL as your database backend. In some cases,
    374    this causes a known mod_python issue due to version conflicts in PHP and
    375    the Python MySQL backend. There's full information in the
    376    `mod_python FAQ entry`_.
    377 
    378 If you continue to have problems setting up mod_python, a good thing to do is
    379 get a barebones mod_python site working, without the Django framework. This is
    380 an easy way to isolate mod_python-specific problems. `Getting mod_python Working`_
    381 details this procedure.
    382 
    383 The next step should be to edit your test code and add an import of any
    384 Django-specific code you're using -- your views, your models, your URLconf,
    385 your RSS configuration, etc. Put these imports in your test handler function
    386 and access your test URL in a browser. If this causes a crash, you've confirmed
    387 it's the importing of Django code that causes the problem. Gradually reduce the
    388 set of imports until it stops crashing, so as to find the specific module that
    389 causes the problem. Drop down further into modules and look into their imports,
    390 as necessary.
    391 
    392 .. _Expat Causing Apache Crash: http://www.dscpl.com.au/wiki/ModPython/Articles/ExpatCausingApacheCrash
    393 .. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp
    394 .. _Getting mod_python Working: http://www.dscpl.com.au/wiki/ModPython/Articles/GettingModPythonWorking
    395 
    396 If you get a UnicodeEncodeError
    397 ===============================
    398 
    399 If you're taking advantage of the internationalization features of Django (see
    400 :doc:`/topics/i18n/index`) and you intend to allow users to upload files, you must
    401 ensure that the environment used to start Apache is configured to accept
    402 non-ASCII file names. If your environment is not correctly configured, you
    403 will trigger ``UnicodeEncodeError`` exceptions when calling functions like
    404 ``os.path()`` on filenames that contain non-ASCII characters.
    405 
    406 To avoid these problems, the environment used to start Apache should contain
    407 settings analogous to the following::
    408 
    409     export LANG='en_US.UTF-8'
    410     export LC_ALL='en_US.UTF-8'
    411 
    412 Consult the documentation for your operating system for the appropriate syntax
    413 and location to put these configuration items; ``/etc/apache2/envvars`` is a
    414 common location on Unix platforms. Once you have added these statements
    415 to your environment, restart Apache.
  • docs/howto/deployment/wsgi/modwsgi.txt

    diff --git a/docs/howto/deployment/wsgi/modwsgi.txt b/docs/howto/deployment/wsgi/modwsgi.txt
    index 1aa4009..8398f12 100644
    a b other approaches:  
    176176
    1771773. Copy the admin static files so that they live within your Apache
    178178   document root.
     179
     180If you get a UnicodeEncodeError
     181===============================
     182
     183If you're taking advantage of the internationalization features of Django (see
     184:doc:`/topics/i18n/index`) and you intend to allow users to upload files, you must
     185ensure that the environment used to start Apache is configured to accept
     186non-ASCII file names. If your environment is not correctly configured, you
     187will trigger ``UnicodeEncodeError`` exceptions when calling functions like
     188``os.path()`` on filenames that contain non-ASCII characters.
     189
     190To avoid these problems, the environment used to start Apache should contain
     191settings analogous to the following::
     192
     193    export LANG='en_US.UTF-8'
     194    export LC_ALL='en_US.UTF-8'
     195
     196Consult the documentation for your operating system for the appropriate syntax
     197and location to put these configuration items; ``/etc/apache2/envvars`` is a
     198common location on Unix platforms. Once you have added these statements
     199to your environment, restart Apache.
  • docs/index.txt

    diff --git a/docs/index.txt b/docs/index.txt
    index a5d2e13..66c8e73 100644
    a b The development process  
    156156  :doc:`Overview <howto/deployment/index>` |
    157157  :doc:`WSGI servers <howto/deployment/wsgi/index>` |
    158158  :doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` |
    159   :doc:`Apache/mod_python (deprecated) <howto/deployment/modpython>` |
    160159  :doc:`Apache authentication <howto/apache-auth>` |
    161160  :doc:`Handling static files <howto/static-files>` |
    162161  :doc:`Tracking code errors by email <howto/error-reporting>`
  • docs/ref/contrib/gis/deployment.txt

    diff --git a/docs/ref/contrib/gis/deployment.txt b/docs/ref/contrib/gis/deployment.txt
    index c50a378..d98fc51 100644
    a b Deploying GeoDjango  
    1313Apache
    1414======
    1515In this section there are some example ``VirtualHost`` directives for
    16 when deploying using either ``mod_python`` or ``mod_wsgi``.  At this
    17 time, we recommend ``mod_wsgi``, as it is now officially recommended
    18 way to deploy Django applications with Apache.  Moreover, if
    19 ``mod_python`` is used, then a prefork version of Apache must also be
    20 used.  As long as ``mod_wsgi`` is configured correctly, it does not
     16when deploying using ``mod_wsgi``, which is now officially the recommended
     17way to deploy Django applications with Apache.
     18As long as ``mod_wsgi`` is configured correctly, it does not
    2119matter whether the version of Apache is prefork or worker.
    2220
    2321.. note::
    Example::  
    5654For more information, please consult Django's
    5755:doc:`mod_wsgi documentation </howto/deployment/wsgi/modwsgi>`.
    5856
    59 ``mod_python``
    60 --------------
    61 
    62 .. warning::
    63     Support for mod_python will be deprecated in a future release of Django. If
    64     you are configuring a new deployment, you are strongly encouraged to
    65     consider using :doc:`mod_wsgi </howto/deployment/wsgi/modwsgi>` or any of
    66     the other :doc:`supported servers </howto/deployment/index>`.
    67 
    68 Example::
    69 
    70     <VirtualHost *:80>
    71 
    72       <Location "/">
    73         SetHandler mod_python
    74         PythonHandler django.core.handlers.modpython
    75         SetEnv DJANGO_SETTINGS_MODULE world.settings
    76         PythonDebug On
    77         PythonPath "['/var/www/apps'] + sys.path"
    78       </Location>
    79 
    80       Alias /media/ "/usr/lib/python2.6/site-packages/django/contrib/admin/media/"
    81       <Location "/media">
    82         SetHandler None
    83       </Location>
    84 
    85     </VirtualHost>
    86 
    87 .. warning::
    88 
    89    When using ``mod_python`` you *must* be using a prefork version of Apache, or
    90    else your GeoDjango application may crash Apache.
    91 
    92 For more information, please consult Django's
    93 :doc:`mod_python documentation </howto/deployment/modpython>`.
    94 
    9557Lighttpd
    9658========
    9759
  • docs/ref/request-response.txt

    diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
    index c0ae73e..ae736b1 100644
    a b All attributes except ``session`` should be considered read-only.  
    5656.. attribute:: HttpRequest.path_info
    5757
    5858    Under some Web server configurations, the portion of the URL after the host
    59     name is split up into a script prefix portion and a path info portion
    60     (this happens, for example, when using the ``django.root`` option
    61     with the :doc:`modpython handler from Apache </howto/deployment/modpython>`).
     59    name is split up into a script prefix portion and a path info portion.
    6260    The ``path_info`` attribute always contains the path info portion of the
    6361    path, no matter what Web server is being used. Using this instead of
    6462    attr:`~HttpRequest.path` can make your code much easier to move between test
    6563    and deployment servers.
    6664
    67     For example, if the ``django.root`` for your application is set to
     65    For example, if the ``WSGIScriptAlias`` for your application is set to
    6866    ``"/minfo"``, then ``path`` might be ``"/minfo/music/bands/the_beatles/"``
    6967    and ``path_info`` would be ``"/music/bands/the_beatles/"``.
    7068
  • docs/topics/http/urls.txt

    diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
    index 1c2849d..73c06ca 100644
    a b find the base URL of the Django project within its Web server  
    10201020(normally, :func:`~django.core.urlresolvers.reverse` takes care of this for
    10211021you). In that case, you can call ``get_script_prefix()``, which will return the
    10221022script prefix portion of the URL for your Django project. If your Django
    1023 project is at the root of its Web server, this is always ``"/"``, but it can be
    1024 changed, for instance  by using ``django.root`` (see :doc:`How to use
    1025 Django with Apache and mod_python </howto/deployment/modpython>`).
     1023project is at the root of its Web server, this is always ``"/"``.
  • tests/regressiontests/requests/tests.py

    diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
    index f986046..5c3cf59 100644
    a b from datetime import datetime, timedelta  
    44from StringIO import StringIO
    55
    66from django.conf import settings
    7 from django.core.handlers.modpython import ModPythonRequest
    87from django.core.handlers.wsgi import WSGIRequest, LimitedStream
    98from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr, UnreadablePostError
    109from django.test.utils import get_warnings_state, restore_warnings_state
    class RequestsTests(unittest.TestCase):  
    5453        self.assertEqual(build_request_repr(request, path_override='/otherpath/', GET_override={u'a': u'b'}, POST_override={u'c': u'd'}, COOKIES_override={u'e': u'f'}, META_override={u'g': u'h'}),
    5554                         u"<WSGIRequest\npath:/otherpath/,\nGET:{u'a': u'b'},\nPOST:{u'c': u'd'},\nCOOKIES:{u'e': u'f'},\nMETA:{u'g': u'h'}>")
    5655
    57     def test_modpythonrequest(self):
    58         class FakeModPythonRequest(ModPythonRequest):
    59            def __init__(self, *args, **kwargs):
    60                super(FakeModPythonRequest, self).__init__(*args, **kwargs)
    61                self._get = self._post = self._meta = self._cookies = {}
    62 
    63         class Dummy:
    64             def get_options(self):
    65                 return {}
    66 
    67         req = Dummy()
    68         req.uri = 'bogus'
    69         request = FakeModPythonRequest(req)
    70         self.assertEqual(request.path, 'bogus')
    71         self.assertEqual(request.GET.keys(), [])
    72         self.assertEqual(request.POST.keys(), [])
    73         self.assertEqual(request.COOKIES.keys(), [])
    74         self.assertEqual(request.META.keys(), [])
    75 
    76     def test_modpythonrequest_repr(self):
    77         class Dummy:
    78             def get_options(self):
    79                 return {}
    80         req = Dummy()
    81         req.uri = '/somepath/'
    82         request = ModPythonRequest(req)
    83         request._get = {u'get-key': u'get-value'}
    84         request._post = {u'post-key': u'post-value'}
    85         request._cookies = {u'post-key': u'post-value'}
    86         request._meta = {u'post-key': u'post-value'}
    87         self.assertEqual(repr(request), u"<ModPythonRequest\npath:/somepath/,\nGET:{u'get-key': u'get-value'},\nPOST:{u'post-key': u'post-value'},\nCOOKIES:{u'post-key': u'post-value'},\nMETA:{u'post-key': u'post-value'}>")
    88         self.assertEqual(build_request_repr(request), repr(request))
    89         self.assertEqual(build_request_repr(request, path_override='/otherpath/', GET_override={u'a': u'b'}, POST_override={u'c': u'd'}, COOKIES_override={u'e': u'f'}, META_override={u'g': u'h'}),
    90                          u"<ModPythonRequest\npath:/otherpath/,\nGET:{u'a': u'b'},\nPOST:{u'c': u'd'},\nCOOKIES:{u'e': u'f'},\nMETA:{u'g': u'h'}>")
    91 
    9256    def test_parse_cookie(self):
    9357        self.assertEqual(parse_cookie('invalid:key=true'), {})
    9458
Back to Top