Django

Code

root/django/trunk/django/core/handlers/base.py

Revision 10347, 8.8 kB (checked in by jacob, 3 months ago)

Reverted [10346] because it effectively breaks USE_I18N by forcing import of translation before settings are ready.

  • Property svn:eol-style set to native
Line 
1 import sys
2
3 from django import http
4 from django.core import signals
5 from django.utils.encoding import force_unicode
6 from django.utils.importlib import import_module
7
8 class BaseHandler(object):
9     # Changes that are always applied to a response (in this order).
10     response_fixes = [
11         http.fix_location_header,
12         http.conditional_content_removal,
13         http.fix_IE_for_attach,
14         http.fix_IE_for_vary,
15     ]
16
17     def __init__(self):
18         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
19
20     def load_middleware(self):
21         """
22         Populate middleware lists from settings.MIDDLEWARE_CLASSES.
23
24         Must be called after the environment is fixed (see __call__).
25         """
26         from django.conf import settings
27         from django.core import exceptions
28         self._view_middleware = []
29         self._response_middleware = []
30         self._exception_middleware = []
31
32         request_middleware = []
33         for middleware_path in settings.MIDDLEWARE_CLASSES:
34             try:
35                 dot = middleware_path.rindex('.')
36             except ValueError:
37                 raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
38             mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
39             try:
40                 mod = import_module(mw_module)
41             except ImportError, e:
42                 raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
43             try:
44                 mw_class = getattr(mod, mw_classname)
45             except AttributeError:
46                 raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
47
48             try:
49                 mw_instance = mw_class()
50             except exceptions.MiddlewareNotUsed:
51                 continue
52
53             if hasattr(mw_instance, 'process_request'):
54                 request_middleware.append(mw_instance.process_request)
55             if hasattr(mw_instance, 'process_view'):
56                 self._view_middleware.append(mw_instance.process_view)
57             if hasattr(mw_instance, 'process_response'):
58                 self._response_middleware.insert(0, mw_instance.process_response)
59             if hasattr(mw_instance, 'process_exception'):
60                 self._exception_middleware.insert(0, mw_instance.process_exception)
61
62         # We only assign to this when initialization is complete as it is used
63         # as a flag for initialization being complete.
64         self._request_middleware = request_middleware
65
66     def get_response(self, request):
67         "Returns an HttpResponse object for the given HttpRequest"
68         from django.core import exceptions, urlresolvers
69         from django.conf import settings
70
71         # Apply request middleware
72         for middleware_method in self._request_middleware:
73             response = middleware_method(request)
74             if response:
75                 return response
76
77         # Get urlconf from request object, if available.  Otherwise use default.
78         urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
79
80         resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
81         try:
82             callback, callback_args, callback_kwargs = resolver.resolve(
83                     request.path_info)
84
85             # Apply view middleware
86             for middleware_method in self._view_middleware:
87                 response = middleware_method(request, callback, callback_args, callback_kwargs)
88                 if response:
89                     return response
90
91             try:
92                 response = callback(request, *callback_args, **callback_kwargs)
93             except Exception, e:
94                 # If the view raised an exception, run it through exception
95                 # middleware, and if the exception middleware returns a
96                 # response, use that. Otherwise, reraise the exception.
97                 for middleware_method in self._exception_middleware:
98                     response = middleware_method(request, e)
99                     if response:
100                         return response
101                 raise
102
103             # Complain if the view returned None (a common error).
104             if response is None:
105                 try:
106                     view_name = callback.func_name # If it's a function
107                 except AttributeError:
108                     view_name = callback.__class__.__name__ + '.__call__' # If it's a class
109                 raise ValueError, "The view %s.%s didn't return an HttpResponse object." % (callback.__module__, view_name)
110
111             return response
112         except http.Http404, e:
113             if settings.DEBUG:
114                 from django.views import debug
115                 return debug.technical_404_response(request, e)
116             else:
117                 try:
118                     callback, param_dict = resolver.resolve404()
119                     return callback(request, **param_dict)
120                 except:
121                     try:
122                         return self.handle_uncaught_exception(request, resolver, sys.exc_info())
123                     finally:
124                         receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
125         except exceptions.PermissionDenied:
126             return http.HttpResponseForbidden('<h1>Permission denied</h1>')
127         except SystemExit:
128             # Allow sys.exit() to actually exit. See tickets #1023 and #4701
129             raise
130         except: # Handle everything else, including SuspiciousOperation, etc.
131             # Get the exception info now, in case another exception is thrown later.
132             exc_info = sys.exc_info()
133             receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
134             return self.handle_uncaught_exception(request, resolver, exc_info)
135
136     def handle_uncaught_exception(self, request, resolver, exc_info):
137         """
138         Processing for any otherwise uncaught exceptions (those that will
139         generate HTTP 500 responses). Can be overridden by subclasses who want
140         customised 500 handling.
141
142         Be *very* careful when overriding this because the error could be
143         caused by anything, so assuming something like the database is always
144         available would be an error.
145         """
146         from django.conf import settings
147         from django.core.mail import mail_admins
148
149         if settings.DEBUG_PROPAGATE_EXCEPTIONS:
150             raise
151
152         if settings.DEBUG:
153             from django.views import debug
154             return debug.technical_500_response(request, *exc_info)
155
156         # When DEBUG is False, send an error message to the admins.
157         subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
158         try:
159             request_repr = repr(request)
160         except:
161             request_repr = "Request repr() unavailable"
162         message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
163         mail_admins(subject, message, fail_silently=True)
164         # Return an HttpResponse that displays a friendly error message.
165         callback, param_dict = resolver.resolve500()
166         return callback(request, **param_dict)
167
168     def _get_traceback(self, exc_info=None):
169         "Helper function to return the traceback as a string"
170         import traceback
171         return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))
172
173     def apply_response_fixes(self, request, response):
174         """
175         Applies each of the functions in self.response_fixes to the request and
176         response, modifying the response in the process. Returns the new
177         response.
178         """
179         for func in self.response_fixes:
180             response = func(request, response)
181         return response
182
183 def get_script_name(environ):
184     """
185     Returns the equivalent of the HTTP request's SCRIPT_NAME environment
186     variable. If Apache mod_rewrite has been used, returns what would have been
187     the script name prior to any rewriting (so it's the script name as seen
188     from the client's perspective), unless DJANGO_USE_POST_REWRITE is set (to
189     anything).
190     """
191     from django.conf import settings
192     if settings.FORCE_SCRIPT_NAME is not None:
193         return force_unicode(settings.FORCE_SCRIPT_NAME)
194
195     # If Apache's mod_rewrite had a whack at the URL, Apache set either
196     # SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any
197     # rewrites. Unfortunately not every webserver (lighttpd!) passes this
198     # information through all the time, so FORCE_SCRIPT_NAME, above, is still
199     # needed.
200     script_url = environ.get('SCRIPT_URL', u'')
201     if not script_url:
202         script_url = environ.get('REDIRECT_URL', u'')
203     if script_url:
204         return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
205     return force_unicode(environ.get('SCRIPT_NAME', u''))
Note: See TracBrowser for help on using the browser.