Merge pull request #885 from loic/ticket19541
Fixed #19541 -- Fixed BaseHandler to enable reversing URLs in response middlewares...
This commit is contained in:
commit
24234555a0
|
@ -74,7 +74,7 @@ class BaseHandler(object):
|
||||||
|
|
||||||
def get_response(self, request):
|
def get_response(self, request):
|
||||||
"Returns an HttpResponse object for the given HttpRequest"
|
"Returns an HttpResponse object for the given HttpRequest"
|
||||||
try:
|
|
||||||
# Setup default url resolver for this thread, this code is outside
|
# Setup default url resolver for this thread, this code is outside
|
||||||
# the try/except so we don't get a spurious "unbound local
|
# the try/except so we don't get a spurious "unbound local
|
||||||
# variable" exception in the event an exception is raised before
|
# variable" exception in the event an exception is raised before
|
||||||
|
@ -152,6 +152,7 @@ class BaseHandler(object):
|
||||||
except:
|
except:
|
||||||
signals.got_request_exception.send(sender=self.__class__, request=request)
|
signals.got_request_exception.send(sender=self.__class__, request=request)
|
||||||
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
|
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
|
||||||
|
|
||||||
except PermissionDenied:
|
except PermissionDenied:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Forbidden (Permission denied): %s', request.path,
|
'Forbidden (Permission denied): %s', request.path,
|
||||||
|
@ -167,17 +168,15 @@ class BaseHandler(object):
|
||||||
sender=self.__class__, request=request)
|
sender=self.__class__, request=request)
|
||||||
response = self.handle_uncaught_exception(request,
|
response = self.handle_uncaught_exception(request,
|
||||||
resolver, sys.exc_info())
|
resolver, sys.exc_info())
|
||||||
|
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
# Allow sys.exit() to actually exit. See tickets #1023 and #4701
|
# Allow sys.exit() to actually exit. See tickets #1023 and #4701
|
||||||
raise
|
raise
|
||||||
|
|
||||||
except: # Handle everything else, including SuspiciousOperation, etc.
|
except: # Handle everything else, including SuspiciousOperation, etc.
|
||||||
# Get the exception info now, in case another exception is thrown later.
|
# Get the exception info now, in case another exception is thrown later.
|
||||||
signals.got_request_exception.send(sender=self.__class__, request=request)
|
signals.got_request_exception.send(sender=self.__class__, request=request)
|
||||||
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
|
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
|
||||||
finally:
|
|
||||||
# Reset URLconf for this thread on the way out for complete
|
|
||||||
# isolation of request.urlconf
|
|
||||||
urlresolvers.set_urlconf(None)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Apply response middleware, regardless of the response
|
# Apply response middleware, regardless of the response
|
||||||
|
|
|
@ -26,7 +26,7 @@ from django.core.management import call_command
|
||||||
from django.core.management.color import no_style
|
from django.core.management.color import no_style
|
||||||
from django.core.servers.basehttp import (WSGIRequestHandler, WSGIServer,
|
from django.core.servers.basehttp import (WSGIRequestHandler, WSGIServer,
|
||||||
WSGIServerException)
|
WSGIServerException)
|
||||||
from django.core.urlresolvers import clear_url_caches
|
from django.core.urlresolvers import clear_url_caches, set_urlconf
|
||||||
from django.db import connection, connections, DEFAULT_DB_ALIAS, transaction
|
from django.db import connection, connections, DEFAULT_DB_ALIAS, transaction
|
||||||
from django.forms.fields import CharField
|
from django.forms.fields import CharField
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
|
@ -497,6 +497,7 @@ class TransactionTestCase(SimpleTestCase):
|
||||||
**{'verbosity': 0, 'database': db_name, 'skip_validation': True})
|
**{'verbosity': 0, 'database': db_name, 'skip_validation': True})
|
||||||
|
|
||||||
def _urlconf_setup(self):
|
def _urlconf_setup(self):
|
||||||
|
set_urlconf(None)
|
||||||
if hasattr(self, 'urls'):
|
if hasattr(self, 'urls'):
|
||||||
self._old_root_urlconf = settings.ROOT_URLCONF
|
self._old_root_urlconf = settings.ROOT_URLCONF
|
||||||
settings.ROOT_URLCONF = self.urls
|
settings.ROOT_URLCONF = self.urls
|
||||||
|
@ -527,6 +528,7 @@ class TransactionTestCase(SimpleTestCase):
|
||||||
skip_validation=True, reset_sequences=False)
|
skip_validation=True, reset_sequences=False)
|
||||||
|
|
||||||
def _urlconf_teardown(self):
|
def _urlconf_teardown(self):
|
||||||
|
set_urlconf(None)
|
||||||
if hasattr(self, '_old_root_urlconf'):
|
if hasattr(self, '_old_root_urlconf'):
|
||||||
settings.ROOT_URLCONF = self._old_root_urlconf
|
settings.ROOT_URLCONF = self._old_root_urlconf
|
||||||
clear_url_caches()
|
clear_url_caches()
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.http import HttpResponse, StreamingHttpResponse
|
||||||
|
|
||||||
from . import urlconf_inner
|
from . import urlconf_inner
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,3 +13,23 @@ class ChangeURLconfMiddleware(object):
|
||||||
class NullChangeURLconfMiddleware(object):
|
class NullChangeURLconfMiddleware(object):
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
request.urlconf = None
|
request.urlconf = None
|
||||||
|
|
||||||
|
class ReverseInnerInResponseMiddleware(object):
|
||||||
|
def process_response(self, *args, **kwargs):
|
||||||
|
return HttpResponse(reverse('inner'))
|
||||||
|
|
||||||
|
class ReverseOuterInResponseMiddleware(object):
|
||||||
|
def process_response(self, *args, **kwargs):
|
||||||
|
return HttpResponse(reverse('outer'))
|
||||||
|
|
||||||
|
class ReverseInnerInStreaming(object):
|
||||||
|
def process_view(self, *args, **kwargs):
|
||||||
|
def stream():
|
||||||
|
yield reverse('inner')
|
||||||
|
return StreamingHttpResponse(stream())
|
||||||
|
|
||||||
|
class ReverseOuterInStreaming(object):
|
||||||
|
def process_view(self, *args, **kwargs):
|
||||||
|
def stream():
|
||||||
|
yield reverse('outer')
|
||||||
|
return StreamingHttpResponse(stream())
|
||||||
|
|
|
@ -462,6 +462,59 @@ class RequestURLconfTests(TestCase):
|
||||||
)
|
)
|
||||||
self.assertRaises(ImproperlyConfigured, self.client.get, '/test/me/')
|
self.assertRaises(ImproperlyConfigured, self.client.get, '/test/me/')
|
||||||
|
|
||||||
|
def test_reverse_inner_in_response_middleware(self):
|
||||||
|
"""
|
||||||
|
Test reversing an URL from the *overridden* URLconf from inside
|
||||||
|
a response middleware.
|
||||||
|
"""
|
||||||
|
settings.MIDDLEWARE_CLASSES += (
|
||||||
|
'%s.ChangeURLconfMiddleware' % middleware.__name__,
|
||||||
|
'%s.ReverseInnerInResponseMiddleware' % middleware.__name__,
|
||||||
|
)
|
||||||
|
response = self.client.get('/second_test/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.content, b'/second_test/')
|
||||||
|
|
||||||
|
def test_reverse_outer_in_response_middleware(self):
|
||||||
|
"""
|
||||||
|
Test reversing an URL from the *default* URLconf from inside
|
||||||
|
a response middleware.
|
||||||
|
"""
|
||||||
|
settings.MIDDLEWARE_CLASSES += (
|
||||||
|
'%s.ChangeURLconfMiddleware' % middleware.__name__,
|
||||||
|
'%s.ReverseOuterInResponseMiddleware' % middleware.__name__,
|
||||||
|
)
|
||||||
|
message = "Reverse for 'outer' with arguments '()' and keyword arguments '{}' not found."
|
||||||
|
with self.assertRaisesMessage(NoReverseMatch, message):
|
||||||
|
self.client.get('/second_test/')
|
||||||
|
|
||||||
|
def test_reverse_inner_in_streaming(self):
|
||||||
|
"""
|
||||||
|
Test reversing an URL from the *overridden* URLconf from inside
|
||||||
|
a streaming response.
|
||||||
|
"""
|
||||||
|
settings.MIDDLEWARE_CLASSES += (
|
||||||
|
'%s.ChangeURLconfMiddleware' % middleware.__name__,
|
||||||
|
'%s.ReverseInnerInStreaming' % middleware.__name__,
|
||||||
|
)
|
||||||
|
response = self.client.get('/second_test/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(b''.join(response), b'/second_test/')
|
||||||
|
|
||||||
|
def test_reverse_outer_in_streaming(self):
|
||||||
|
"""
|
||||||
|
Test reversing an URL from the *default* URLconf from inside
|
||||||
|
a streaming response.
|
||||||
|
"""
|
||||||
|
settings.MIDDLEWARE_CLASSES += (
|
||||||
|
'%s.ChangeURLconfMiddleware' % middleware.__name__,
|
||||||
|
'%s.ReverseOuterInStreaming' % middleware.__name__,
|
||||||
|
)
|
||||||
|
message = "Reverse for 'outer' with arguments '()' and keyword arguments '{}' not found."
|
||||||
|
with self.assertRaisesMessage(NoReverseMatch, message):
|
||||||
|
self.client.get('/second_test/')
|
||||||
|
b''.join(self.client.get('/second_test/'))
|
||||||
|
|
||||||
class ErrorHandlerResolutionTests(TestCase):
|
class ErrorHandlerResolutionTests(TestCase):
|
||||||
"""Tests for handler404 and handler500"""
|
"""Tests for handler404 and handler500"""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue