diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index 30843bf7f7..eba7811529 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -49,7 +49,12 @@ class BaseHandler(object): mw_class = import_string(middleware_path) try: mw_instance = mw_class() - except MiddlewareNotUsed: + except MiddlewareNotUsed as exc: + if settings.DEBUG: + if six.text_type(exc): + logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc) + else: + logger.debug('MiddlewareNotUsed: %r', middleware_path) continue if hasattr(mw_instance, 'process_request'): diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 1593f26b79..b06c32ce5f 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -337,6 +337,10 @@ Middleware ` attribute allows you to customize the redirects issued by the middleware. +* A debug message will be logged to the ``django.request`` logger when a + middleware raises a :exc:`~django.core.exceptions.MiddlewareNotUsed` exception + in :setting:`DEBUG` mode. + Migrations ^^^^^^^^^^ diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt index 3a05e64751..cc7607da0a 100644 --- a/docs/topics/http/middleware.txt +++ b/docs/topics/http/middleware.txt @@ -269,7 +269,14 @@ Marking middleware as unused It's sometimes useful to determine at run-time whether a piece of middleware should be used. In these cases, your middleware's ``__init__`` method may raise :exc:`django.core.exceptions.MiddlewareNotUsed`. Django will then remove -that piece of middleware from the middleware process. +that piece of middleware from the middleware process and a debug message will +be logged to the ``django.request`` logger when :setting:`DEBUG` is set to +``True``. + +.. versionchanged:: 1.8 + + Previously, :exc:`~django.core.exceptions.MiddlewareNotUsed` exceptions + weren't logged. Guidelines ---------- diff --git a/tests/middleware_exceptions/tests.py b/tests/middleware_exceptions/tests.py index 473e726d8b..8a2ddfa4a1 100644 --- a/tests/middleware_exceptions/tests.py +++ b/tests/middleware_exceptions/tests.py @@ -1,11 +1,13 @@ import sys from django.conf import settings +from django.core.exceptions import MiddlewareNotUsed from django.core.signals import got_request_exception from django.http import HttpResponse from django.template.response import TemplateResponse from django.template import Template -from django.test import TestCase, override_settings +from django.test import RequestFactory, TestCase, override_settings +from django.test.utils import patch_logger class TestException(Exception): @@ -832,3 +834,65 @@ class RootUrlconfTests(TestCase): # the previously defined settings. del settings.ROOT_URLCONF self.assertRaises(AttributeError, self.client.get, "/middleware_exceptions/view/") + + +class MyMiddleware(object): + + def __init__(self): + raise MiddlewareNotUsed + + def process_request(self, request): + pass + + +class MyMiddlewareWithExceptionMessage(object): + + def __init__(self): + raise MiddlewareNotUsed('spam eggs') + + def process_request(self, request): + pass + + +@override_settings( + DEBUG=True, + ROOT_URLCONF='middleware_exceptions.urls', +) +class MiddlewareNotUsedTests(TestCase): + + rf = RequestFactory() + + def test_raise_exception(self): + request = self.rf.get('middleware_exceptions/view/') + with self.assertRaises(MiddlewareNotUsed): + MyMiddleware().process_request(request) + + @override_settings(MIDDLEWARE_CLASSES=( + 'middleware_exceptions.tests.MyMiddleware', + )) + def test_log(self): + with patch_logger('django.request', 'debug') as calls: + self.client.get('/middleware_exceptions/view/') + self.assertEqual(len(calls), 1) + self.assertEqual( + calls[0], + "MiddlewareNotUsed: 'middleware_exceptions.tests.MyMiddleware'" + ) + + @override_settings(MIDDLEWARE_CLASSES=( + 'middleware_exceptions.tests.MyMiddlewareWithExceptionMessage', + )) + def test_log_custom_message(self): + with patch_logger('django.request', 'debug') as calls: + self.client.get('/middleware_exceptions/view/') + self.assertEqual(len(calls), 1) + self.assertEqual( + calls[0], + "MiddlewareNotUsed('middleware_exceptions.tests.MyMiddlewareWithExceptionMessage'): spam eggs" + ) + + @override_settings(DEBUG=False) + def test_do_not_log_when_debug_is_false(self): + with patch_logger('django.request', 'debug') as calls: + self.client.get('/middleware_exceptions/view/') + self.assertEqual(len(calls), 0)