Changed/fixed the way Django handles SCRIPT_NAME and PATH_INFO (or
equivalents). Basically, URL resolving will only use the PATH_INFO and the SCRIPT_NAME will be prepended by reverse() automatically. Allows for more portable development and installation. Also exposes SCRIPT_NAME in the HttpRequest instance. There are a number of cases where things don't work completely transparently, so mod_python and fastcgi users should read the relevant docs. Fixed #285, #1516, #3414. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8015 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
ca7ee4be17
commit
bfcecbffd3
|
@ -188,6 +188,9 @@ APPEND_SLASH = True
|
||||||
# Whether to prepend the "www." subdomain to URLs that don't have it.
|
# Whether to prepend the "www." subdomain to URLs that don't have it.
|
||||||
PREPEND_WWW = False
|
PREPEND_WWW = False
|
||||||
|
|
||||||
|
# Override the server-derived value of SCRIPT_NAME
|
||||||
|
FORCE_SCRIPT_NAME = None
|
||||||
|
|
||||||
# List of compiled regular expression objects representing User-Agent strings
|
# List of compiled regular expression objects representing User-Agent strings
|
||||||
# that are not allowed to visit any page, systemwide. Use this for bad
|
# that are not allowed to visit any page, systemwide. Use this for bad
|
||||||
# robots/crawlers. Here are a few examples:
|
# robots/crawlers. Here are a few examples:
|
||||||
|
|
|
@ -3,6 +3,7 @@ import sys
|
||||||
from django import http
|
from django import http
|
||||||
from django.core import signals
|
from django.core import signals
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
|
from django.utils.encoding import force_unicode
|
||||||
|
|
||||||
class BaseHandler(object):
|
class BaseHandler(object):
|
||||||
# Changes that are always applied to a response (in this order).
|
# Changes that are always applied to a response (in this order).
|
||||||
|
@ -73,7 +74,8 @@ class BaseHandler(object):
|
||||||
|
|
||||||
resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
|
resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
|
||||||
try:
|
try:
|
||||||
callback, callback_args, callback_kwargs = resolver.resolve(request.path)
|
callback, callback_args, callback_kwargs = resolver.resolve(
|
||||||
|
request.path_info)
|
||||||
|
|
||||||
# Apply view middleware
|
# Apply view middleware
|
||||||
for middleware_method in self._view_middleware:
|
for middleware_method in self._view_middleware:
|
||||||
|
@ -170,3 +172,27 @@ class BaseHandler(object):
|
||||||
response = func(request, response)
|
response = func(request, response)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def get_script_name(environ):
|
||||||
|
"""
|
||||||
|
Returns the equivalent of the HTTP request's SCRIPT_NAME environment
|
||||||
|
variable. If Apache mod_rewrite has been used, returns what would have been
|
||||||
|
the script name prior to any rewriting (so it's the script name as seen
|
||||||
|
from the client's perspective), unless DJANGO_USE_POST_REWRITE is set (to
|
||||||
|
anything).
|
||||||
|
"""
|
||||||
|
from django.conf import settings
|
||||||
|
if settings.FORCE_SCRIPT_NAME is not None:
|
||||||
|
return force_unicode(settings.FORCE_SCRIPT_NAME)
|
||||||
|
|
||||||
|
# If Apache's mod_rewrite had a whack at the URL, Apache set either
|
||||||
|
# SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any
|
||||||
|
# rewrites. Unfortunately not every webserver (lighttpd!) passes this
|
||||||
|
# information through all the time, so FORCE_SCRIPT_NAME, above, is still
|
||||||
|
# needed.
|
||||||
|
script_url = environ.get('SCRIPT_URL', u'')
|
||||||
|
if not script_url:
|
||||||
|
script_url = environ.get('REDIRECT_URL', u'')
|
||||||
|
if script_url:
|
||||||
|
return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
|
||||||
|
return force_unicode(environ.get('SCRIPT_NAME', u''))
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from pprint import pformat
|
||||||
from django import http
|
from django import http
|
||||||
from django.core import signals
|
from django.core import signals
|
||||||
from django.core.handlers.base import BaseHandler
|
from django.core.handlers.base import BaseHandler
|
||||||
|
from django.core.urlresolvers import set_script_prefix
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.utils import datastructures
|
from django.utils import datastructures
|
||||||
from django.utils.encoding import force_unicode, smart_str
|
from django.utils.encoding import force_unicode, smart_str
|
||||||
|
@ -15,7 +16,21 @@ from django.utils.encoding import force_unicode, smart_str
|
||||||
class ModPythonRequest(http.HttpRequest):
|
class ModPythonRequest(http.HttpRequest):
|
||||||
def __init__(self, req):
|
def __init__(self, req):
|
||||||
self._req = req
|
self._req = req
|
||||||
|
# FIXME: This isn't ideal. The request URI may be encoded (it's
|
||||||
|
# non-normalized) slightly differently to the "real" SCRIPT_NAME
|
||||||
|
# and PATH_INFO values. This causes problems when we compute path_info,
|
||||||
|
# below. For now, don't use script names that will be subject to
|
||||||
|
# encoding/decoding.
|
||||||
self.path = force_unicode(req.uri)
|
self.path = force_unicode(req.uri)
|
||||||
|
root = req.get_options().get('django.root', '')
|
||||||
|
self.django_root = root
|
||||||
|
# req.path_info isn't necessarily computed correctly in all
|
||||||
|
# circumstances (it's out of mod_python's control a bit), so we use
|
||||||
|
# req.uri and some string manipulations to get the right value.
|
||||||
|
if root and req.uri.startswith(root):
|
||||||
|
self.path_info = force_unicode(req.uri[len(root):])
|
||||||
|
else:
|
||||||
|
self.path_info = self.path
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
# Since this is called as part of error handling, we need to be very
|
# Since this is called as part of error handling, we need to be very
|
||||||
|
@ -100,7 +115,7 @@ class ModPythonRequest(http.HttpRequest):
|
||||||
'CONTENT_LENGTH': self._req.clength, # This may be wrong
|
'CONTENT_LENGTH': self._req.clength, # This may be wrong
|
||||||
'CONTENT_TYPE': self._req.content_type, # This may be wrong
|
'CONTENT_TYPE': self._req.content_type, # This may be wrong
|
||||||
'GATEWAY_INTERFACE': 'CGI/1.1',
|
'GATEWAY_INTERFACE': 'CGI/1.1',
|
||||||
'PATH_INFO': self._req.path_info,
|
'PATH_INFO': self.path_info,
|
||||||
'PATH_TRANSLATED': None, # Not supported
|
'PATH_TRANSLATED': None, # Not supported
|
||||||
'QUERY_STRING': self._req.args,
|
'QUERY_STRING': self._req.args,
|
||||||
'REMOTE_ADDR': self._req.connection.remote_ip,
|
'REMOTE_ADDR': self._req.connection.remote_ip,
|
||||||
|
@ -108,7 +123,7 @@ class ModPythonRequest(http.HttpRequest):
|
||||||
'REMOTE_IDENT': self._req.connection.remote_logname,
|
'REMOTE_IDENT': self._req.connection.remote_logname,
|
||||||
'REMOTE_USER': self._req.user,
|
'REMOTE_USER': self._req.user,
|
||||||
'REQUEST_METHOD': self._req.method,
|
'REQUEST_METHOD': self._req.method,
|
||||||
'SCRIPT_NAME': None, # Not supported
|
'SCRIPT_NAME': self.django_root,
|
||||||
'SERVER_NAME': self._req.server.server_hostname,
|
'SERVER_NAME': self._req.server.server_hostname,
|
||||||
'SERVER_PORT': self._req.server.port,
|
'SERVER_PORT': self._req.server.port,
|
||||||
'SERVER_PROTOCOL': self._req.protocol,
|
'SERVER_PROTOCOL': self._req.protocol,
|
||||||
|
@ -153,6 +168,7 @@ class ModPythonHandler(BaseHandler):
|
||||||
if self._request_middleware is None:
|
if self._request_middleware is None:
|
||||||
self.load_middleware()
|
self.load_middleware()
|
||||||
|
|
||||||
|
set_script_prefix(req.get_options().get('django.root', ''))
|
||||||
dispatcher.send(signal=signals.request_started)
|
dispatcher.send(signal=signals.request_started)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -7,7 +7,8 @@ except ImportError:
|
||||||
|
|
||||||
from django import http
|
from django import http
|
||||||
from django.core import signals
|
from django.core import signals
|
||||||
from django.core.handlers.base import BaseHandler
|
from django.core.handlers import base
|
||||||
|
from django.core.urlresolvers import set_script_prefix
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.utils import datastructures
|
from django.utils import datastructures
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
|
@ -74,9 +75,14 @@ def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
|
||||||
|
|
||||||
class WSGIRequest(http.HttpRequest):
|
class WSGIRequest(http.HttpRequest):
|
||||||
def __init__(self, environ):
|
def __init__(self, environ):
|
||||||
|
script_name = base.get_script_name(environ)
|
||||||
|
path_info = force_unicode(environ.get('PATH_INFO', '/'))
|
||||||
self.environ = environ
|
self.environ = environ
|
||||||
self.path = force_unicode(environ['PATH_INFO'])
|
self.path_info = path_info
|
||||||
|
self.path = '%s%s' % (script_name, path_info)
|
||||||
self.META = environ
|
self.META = environ
|
||||||
|
self.META['PATH_INFO'] = path_info
|
||||||
|
self.META['SCRIPT_NAME'] = script_name
|
||||||
self.method = environ['REQUEST_METHOD'].upper()
|
self.method = environ['REQUEST_METHOD'].upper()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -178,7 +184,7 @@ class WSGIRequest(http.HttpRequest):
|
||||||
REQUEST = property(_get_request)
|
REQUEST = property(_get_request)
|
||||||
raw_post_data = property(_get_raw_post_data)
|
raw_post_data = property(_get_raw_post_data)
|
||||||
|
|
||||||
class WSGIHandler(BaseHandler):
|
class WSGIHandler(base.BaseHandler):
|
||||||
initLock = Lock()
|
initLock = Lock()
|
||||||
request_class = WSGIRequest
|
request_class = WSGIRequest
|
||||||
|
|
||||||
|
@ -194,6 +200,7 @@ class WSGIHandler(BaseHandler):
|
||||||
self.load_middleware()
|
self.load_middleware()
|
||||||
self.initLock.release()
|
self.initLock.release()
|
||||||
|
|
||||||
|
set_script_prefix(base.get_script_name(environ))
|
||||||
dispatcher.send(signal=signals.request_started)
|
dispatcher.send(signal=signals.request_started)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -7,11 +7,13 @@ a string) and returns a tuple in this format:
|
||||||
(view_function, function_args, function_kwargs)
|
(view_function, function_args, function_kwargs)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||||
from django.utils.encoding import iri_to_uri, force_unicode, smart_str
|
from django.utils.encoding import iri_to_uri, force_unicode, smart_str
|
||||||
from django.utils.functional import memoize
|
from django.utils.functional import memoize
|
||||||
import re
|
from django.utils.thread_support import currentThread
|
||||||
|
|
||||||
try:
|
try:
|
||||||
reversed
|
reversed
|
||||||
|
@ -21,6 +23,11 @@ except NameError:
|
||||||
_resolver_cache = {} # Maps urlconf modules to RegexURLResolver instances.
|
_resolver_cache = {} # Maps urlconf modules to RegexURLResolver instances.
|
||||||
_callable_cache = {} # Maps view and url pattern names to their view functions.
|
_callable_cache = {} # Maps view and url pattern names to their view functions.
|
||||||
|
|
||||||
|
# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
|
||||||
|
# the current thread (which is the only one we ever access), it is assumed to
|
||||||
|
# be empty.
|
||||||
|
_prefixes = {}
|
||||||
|
|
||||||
class Resolver404(Http404):
|
class Resolver404(Http404):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -291,13 +298,33 @@ class RegexURLResolver(object):
|
||||||
def resolve(path, urlconf=None):
|
def resolve(path, urlconf=None):
|
||||||
return get_resolver(urlconf).resolve(path)
|
return get_resolver(urlconf).resolve(path)
|
||||||
|
|
||||||
def reverse(viewname, urlconf=None, args=None, kwargs=None):
|
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None):
|
||||||
args = args or []
|
args = args or []
|
||||||
kwargs = kwargs or {}
|
kwargs = kwargs or {}
|
||||||
return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs))
|
if prefix is None:
|
||||||
|
prefix = get_script_prefix()
|
||||||
|
return iri_to_uri(u'%s%s' % (prefix, get_resolver(urlconf).reverse(viewname,
|
||||||
|
*args, **kwargs)))
|
||||||
|
|
||||||
def clear_url_caches():
|
def clear_url_caches():
|
||||||
global _resolver_cache
|
global _resolver_cache
|
||||||
global _callable_cache
|
global _callable_cache
|
||||||
_resolver_cache.clear()
|
_resolver_cache.clear()
|
||||||
_callable_cache.clear()
|
_callable_cache.clear()
|
||||||
|
|
||||||
|
def set_script_prefix(prefix):
|
||||||
|
"""
|
||||||
|
Sets the script prefix for the current thread.
|
||||||
|
"""
|
||||||
|
if not prefix.endswith('/'):
|
||||||
|
prefix += '/'
|
||||||
|
_prefixes[currentThread()] = prefix
|
||||||
|
|
||||||
|
def get_script_prefix():
|
||||||
|
"""
|
||||||
|
Returns the currently active script prefix. Useful for client code that
|
||||||
|
wishes to construct their own URLs manually (although accessing the request
|
||||||
|
instance is normally going to be a lot cleaner).
|
||||||
|
"""
|
||||||
|
return _prefixes.get(currentThread(), u'/')
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ class HttpRequest(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {}
|
self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {}
|
||||||
self.path = ''
|
self.path = ''
|
||||||
|
self.path_info = ''
|
||||||
self.method = None
|
self.method = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -442,3 +443,4 @@ def str_to_unicode(s, encoding):
|
||||||
return unicode(s, encoding, 'replace')
|
return unicode(s, encoding, 'replace')
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ class Client:
|
||||||
'PATH_INFO': '/',
|
'PATH_INFO': '/',
|
||||||
'QUERY_STRING': '',
|
'QUERY_STRING': '',
|
||||||
'REQUEST_METHOD': 'GET',
|
'REQUEST_METHOD': 'GET',
|
||||||
'SCRIPT_NAME': None,
|
'SCRIPT_NAME': '',
|
||||||
'SERVER_NAME': 'testserver',
|
'SERVER_NAME': 'testserver',
|
||||||
'SERVER_PORT': 80,
|
'SERVER_PORT': 80,
|
||||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
"""
|
||||||
|
Code used in a couple of places to work with the current thread's environment.
|
||||||
|
Current users include i18n and request prefix handling.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import threading
|
||||||
|
currentThread = threading.currentThread
|
||||||
|
except ImportError:
|
||||||
|
def currentThread():
|
||||||
|
return "no threading"
|
||||||
|
|
|
@ -8,18 +8,7 @@ import gettext as gettext_module
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
from django.utils.safestring import mark_safe, SafeData
|
from django.utils.safestring import mark_safe, SafeData
|
||||||
|
from django.utils.thread_support import currentThread
|
||||||
try:
|
|
||||||
import threading
|
|
||||||
hasThreads = True
|
|
||||||
except ImportError:
|
|
||||||
hasThreads = False
|
|
||||||
|
|
||||||
if hasThreads:
|
|
||||||
currentThread = threading.currentThread
|
|
||||||
else:
|
|
||||||
def currentThread():
|
|
||||||
return 'no threading'
|
|
||||||
|
|
||||||
# Translations are cached in a dictionary for every language+app tuple.
|
# Translations are cached in a dictionary for every language+app tuple.
|
||||||
# The active translations are stored by threadid to make them thread local.
|
# The active translations are stored by threadid to make them thread local.
|
||||||
|
|
|
@ -79,9 +79,9 @@ your ``manage.py`` is), and then run ``manage.py`` with the ``runfcgi`` option::
|
||||||
If you specify ``help`` as the only option after ``runfcgi``, it'll display a
|
If you specify ``help`` as the only option after ``runfcgi``, it'll display a
|
||||||
list of all the available options.
|
list of all the available options.
|
||||||
|
|
||||||
You'll need to specify either a ``socket``, ``protocol`` or both ``host`` and ``port``.
|
You'll need to specify either a ``socket``, ``protocol`` or both ``host`` and
|
||||||
Then, when you set up your Web server, you'll just need to point it at the host/port
|
``port``. Then, when you set up your Web server, you'll just need to point it
|
||||||
or socket you specified when starting the FastCGI server.
|
at the host/port or socket you specified when starting the FastCGI server.
|
||||||
|
|
||||||
Protocols
|
Protocols
|
||||||
---------
|
---------
|
||||||
|
@ -209,6 +209,9 @@ This is probably the most common case, if you're using Django's admin site::
|
||||||
|
|
||||||
.. _mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
|
.. _mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
|
||||||
|
|
||||||
|
Django will automatically use the pre-rewrite version of the URL when
|
||||||
|
constructing URLs with the ``{% url %}`` template tag (and similar methods).
|
||||||
|
|
||||||
lighttpd setup
|
lighttpd setup
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -336,3 +339,30 @@ detailed above.
|
||||||
|
|
||||||
.. _modpython: ../modpython/#serving-the-admin-files
|
.. _modpython: ../modpython/#serving-the-admin-files
|
||||||
|
|
||||||
|
Forcing the URL prefix to a particular value
|
||||||
|
============================================
|
||||||
|
|
||||||
|
Because many of these fastcgi-based solutions require rewriting the URL at
|
||||||
|
some point inside the webserver, the path information that Django sees may not
|
||||||
|
resemble the original URL that was passed in. This is a problem if the Django
|
||||||
|
application is being served from under a particular prefix and you want your
|
||||||
|
URLs from the ``{% url %}`` tag to look like the prefix, rather than the
|
||||||
|
rewritten version, which might contain, for example, ``mysite.fcgi``.
|
||||||
|
|
||||||
|
Django makes a good attempt to work out what the real script name prefix
|
||||||
|
should be. In particular, if the webserver sets the ``SCRIPT_URL`` (specific
|
||||||
|
to Apache's mod_rewrite), or ``REDIRECT_URL`` (set by a few servers, including
|
||||||
|
Apache + mod_rewrite in some situations), Django will work out the original
|
||||||
|
prefix automatically.
|
||||||
|
|
||||||
|
In the cases where Django cannot work out the prefix correctly and where you
|
||||||
|
wan the original value to be used in URLs, you can set the
|
||||||
|
``FORCE_SCRIPT_NAME`` setting in your main ``settings`` file. This sets the
|
||||||
|
script name uniformly for every URL served via that settings file. Thus you'll
|
||||||
|
need to use different settings files is you want different sets of URLs to
|
||||||
|
have different script names in this case, but that is a rare situation.
|
||||||
|
|
||||||
|
As an example of how to use it, if your Django configuration is serving all of
|
||||||
|
the URLs under ``'/'`` and you wanted to use this setting, you would set
|
||||||
|
``FORCE_SCRIPT_NAME = ''`` in your settings file.
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ Then edit your ``httpd.conf`` file and add the following::
|
||||||
SetHandler python-program
|
SetHandler python-program
|
||||||
PythonHandler django.core.handlers.modpython
|
PythonHandler django.core.handlers.modpython
|
||||||
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
|
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
|
||||||
|
PythonOption django.root /mysite
|
||||||
PythonDebug On
|
PythonDebug On
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
|
@ -45,6 +46,24 @@ This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
|
||||||
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
|
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
|
||||||
so mod_python knows which settings to use.
|
so mod_python knows which settings to use.
|
||||||
|
|
||||||
|
**New in Django development version:** Because mod_python does not know we are
|
||||||
|
serving this site from underneath the ``/mysite/`` prefix, this value needs to
|
||||||
|
be passed through to the mod_python handler in Django, via the ``PythonOption
|
||||||
|
django.root ...`` line. The value set on that line (the last item) should
|
||||||
|
match the string given in the ``<Location ...>`` directive. The effect of this
|
||||||
|
is that Django will automatically strip the ``/mysite`` string from the front
|
||||||
|
of any URLs before matching them against your ``URLConf`` patterns. If you
|
||||||
|
later move your site to live under ``/mysite2``, you will not have to change
|
||||||
|
anything except the ``django.root`` option in the config file.
|
||||||
|
|
||||||
|
When using ``django.root`` you should make sure that what's left, after the
|
||||||
|
prefix has been removed, begins with a slash. Your URLConf patterns that are
|
||||||
|
expecting an initial slash will then work correctly. In the above example,
|
||||||
|
since we want to send things like ``/mysite/admin/`` to ``/admin/``, we need
|
||||||
|
to remove the string ``/mysite`` from the beginning, so that is the
|
||||||
|
``django.root`` value. It would be an error to use ``/mysite/`` (with a
|
||||||
|
trailing slash) in this case.
|
||||||
|
|
||||||
Note that we're using the ``<Location>`` directive, not the ``<Directory>``
|
Note that we're using the ``<Location>`` directive, not the ``<Directory>``
|
||||||
directive. The latter is used for pointing at places on your filesystem,
|
directive. The latter is used for pointing at places on your filesystem,
|
||||||
whereas ``<Location>`` points at places in the URL structure of a Web site.
|
whereas ``<Location>`` points at places in the URL structure of a Web site.
|
||||||
|
@ -59,6 +78,7 @@ computer, you'll have to tell mod_python where your project can be found:
|
||||||
SetHandler python-program
|
SetHandler python-program
|
||||||
PythonHandler django.core.handlers.modpython
|
PythonHandler django.core.handlers.modpython
|
||||||
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
|
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
|
||||||
|
PythonOption django.root /mysite
|
||||||
PythonDebug On
|
PythonDebug On
|
||||||
**PythonPath "['/path/to/project'] + sys.path"**
|
**PythonPath "['/path/to/project'] + sys.path"**
|
||||||
</Location>
|
</Location>
|
||||||
|
|
|
@ -578,6 +578,16 @@ these paths should use Unix-style forward slashes, even on Windows. See
|
||||||
|
|
||||||
.. _Testing Django Applications: ../testing/
|
.. _Testing Django Applications: ../testing/
|
||||||
|
|
||||||
|
FORCE_SCRIPT_NAME
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
If not ``None``, this will be used as the value of the ``SCRIPT_NAME``
|
||||||
|
environment variable in any HTTP request. This setting can be used to override
|
||||||
|
the server-provided value of ``SCRIPT_NAME``, which may be a rewritten version
|
||||||
|
of the preferred value or not supplied at all.
|
||||||
|
|
||||||
IGNORABLE_404_ENDS
|
IGNORABLE_404_ENDS
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ META:{...}>
|
||||||
... def __init__(self, *args, **kwargs):
|
... def __init__(self, *args, **kwargs):
|
||||||
... super(FakeModPythonRequest, self).__init__(*args, **kwargs)
|
... super(FakeModPythonRequest, self).__init__(*args, **kwargs)
|
||||||
... self._get = self._post = self._meta = self._cookies = {}
|
... self._get = self._post = self._meta = self._cookies = {}
|
||||||
>>> class Dummy: pass
|
>>> class Dummy:
|
||||||
...
|
... def get_options(self):
|
||||||
|
... return {}
|
||||||
>>> req = Dummy()
|
>>> req = Dummy()
|
||||||
>>> req.uri = 'bogus'
|
>>> req.uri = 'bogus'
|
||||||
>>> print repr(FakeModPythonRequest(req))
|
>>> print repr(FakeModPythonRequest(req))
|
||||||
|
|
Loading…
Reference in New Issue