diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index 9388fae49e..6fb28d96ae 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -1,3 +1,5 @@
+from django.core import signals
+from django.dispatch import dispatcher
from django.utils import httpwrappers
class BaseHandler:
@@ -48,13 +50,9 @@ class BaseHandler:
def get_response(self, path, request):
"Returns an HttpResponse object for the given HttpRequest"
from django.core import exceptions, urlresolvers
- from django.db import connection, DatabaseError
from django.core.mail import mail_admins
from django.conf.settings import DEBUG, INTERNAL_IPS, ROOT_URLCONF
- # Reset query list per request.
- connection.queries = []
-
# Apply request middleware
for middleware_method in self._request_middleware:
response = middleware_method(request)
@@ -94,22 +92,15 @@ class BaseHandler:
else:
callback, param_dict = resolver.resolve404()
return callback(request, **param_dict)
- except DatabaseError:
- connection.rollback()
- if DEBUG:
- return self.get_technical_error_response(request)
- else:
- subject = 'Database error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
- message = "%s\n\n%s" % (self._get_traceback(), request)
- mail_admins(subject, message, fail_silently=True)
- return self.get_friendly_error_response(request, resolver)
except exceptions.PermissionDenied:
return httpwrappers.HttpResponseForbidden('
Permission denied
')
except: # Handle everything else, including SuspiciousOperation, etc.
if DEBUG:
return self.get_technical_error_response(request)
else:
- subject = 'Coding error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
+ receivers = dispatcher.send(signal=signals.got_request_exception)
+ # When DEBUG is False, send an error message to the admins.
+ subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
try:
request_repr = repr(request)
except:
@@ -121,7 +112,7 @@ class BaseHandler:
def get_friendly_error_response(self, request, resolver):
"""
Returns an HttpResponse that displays a PUBLIC error message for a
- fundamental database or coding error.
+ fundamental error.
"""
from django.core import urlresolvers
callback, param_dict = resolver.resolve500()
@@ -130,7 +121,7 @@ class BaseHandler:
def get_technical_error_response(self, request, is404=False, exception=None):
"""
Returns an HttpResponse that displays a TECHNICAL error message for a
- fundamental database or coding error.
+ fundamental error.
"""
import sys
from django.views import debug
diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
index 59909fb803..62c6d73a2d 100644
--- a/django/core/handlers/modpython.py
+++ b/django/core/handlers/modpython.py
@@ -1,4 +1,6 @@
from django.core.handlers.base import BaseHandler
+from django.core import signals
+from django.dispatch import dispatcher
from django.utils import datastructures, httpwrappers
from pprint import pformat
import os
@@ -128,17 +130,17 @@ class ModPythonHandler(BaseHandler):
# now that the environ works we can see the correct settings, so imports
# that use settings now can work
from django.conf import settings
- from django.db import connection
# if we need to set up middleware, now that settings works we can do it now.
if self._request_middleware is None:
self.load_middleware()
+ dispatcher.send(signal=signals.request_started)
try:
request = ModPythonRequest(req)
response = self.get_response(req.uri, request)
finally:
- connection.close()
+ dispatcher.send(signal=signals.request_finished)
# Apply response middleware
for middleware_method in self._response_middleware:
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 1f5d5ea2d3..19eec253d6 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -1,4 +1,6 @@
from django.core.handlers.base import BaseHandler
+from django.core import signals
+from django.dispatch import dispatcher
from django.utils import datastructures, httpwrappers
from pprint import pformat
@@ -143,18 +145,18 @@ class WSGIRequest(httpwrappers.HttpRequest):
class WSGIHandler(BaseHandler):
def __call__(self, environ, start_response):
from django.conf import settings
- from django.db import connection
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
if self._request_middleware is None:
self.load_middleware()
+ dispatcher.send(signal=signals.request_started)
try:
request = WSGIRequest(environ)
response = self.get_response(request.path, request)
finally:
- connection.close()
+ dispatcher.send(signal=signals.request_finished)
# Apply response middleware
for middleware_method in self._response_middleware:
diff --git a/django/core/signals.py b/django/core/signals.py
new file mode 100644
index 0000000000..7a236079a5
--- /dev/null
+++ b/django/core/signals.py
@@ -0,0 +1,3 @@
+request_started = object()
+request_finished = object()
+got_request_exception = object()
diff --git a/django/db/__init__.py b/django/db/__init__.py
index 03bf198d68..9274e4032f 100644
--- a/django/db/__init__.py
+++ b/django/db/__init__.py
@@ -1,4 +1,6 @@
from django.conf.settings import DATABASE_ENGINE
+from django.core import signals
+from django.dispatch import dispatcher
__all__ = ('backend', 'connection', 'DatabaseError')
@@ -23,3 +25,17 @@ get_creation_module = lambda: __import__('django.db.backends.%s.creation' % DATA
connection = backend.DatabaseWrapper()
DatabaseError = backend.DatabaseError
+
+# Register an event that closes the database connection
+# when a Django request is finished.
+dispatcher.connect(lambda: connection.close(), signal=signals.request_finished)
+
+# Register an event that resets connection.queries
+# when a Django request is started.
+def reset_queries():
+ connection.queries = []
+dispatcher.connect(reset_queries, signal=signals.request_started)
+
+# Register an event that rolls back the connection
+# when a Django request has an exception.
+dispatcher.connect(lambda: connection.rollback(), signal=signals.got_request_exception)