diff --git a/rest_framework/request.py b/rest_framework/request.py index f5738bfd5..43db3a4a1 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -143,6 +143,7 @@ class Request(object): self._full_data = Empty self._content_type = Empty self._stream = Empty + self.debug_plaintext_traceback = None if self.parser_context is None: self.parser_context = {} @@ -391,3 +392,8 @@ class Request(object): '`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` ' 'since version 3.0, and has been fully removed as of version 3.2.' ) + + def force_plaintext_errors(self, value): + # Hack to allow our exception handler to force choice of + # plaintext or html error responses. + self._request.is_ajax = lambda: value diff --git a/rest_framework/views.py b/rest_framework/views.py index b86bb7eaa..1262d69d2 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -3,17 +3,14 @@ Provides an APIView class that is the base of all views in REST framework. """ from __future__ import unicode_literals -import sys - from django.conf import settings from django.core.exceptions import PermissionDenied from django.db import models from django.http import Http404 -from django.http.response import HttpResponse, HttpResponseBase +from django.http.response import HttpResponseBase from django.utils import six from django.utils.encoding import smart_text from django.utils.translation import ugettext_lazy as _ -from django.views import debug from django.views.decorators.csrf import csrf_exempt from django.views.generic import View @@ -95,11 +92,6 @@ def exception_handler(exc, context): set_rollback() return Response(data, status=status.HTTP_403_FORBIDDEN) - # throw django's error page if debug is True - if settings.DEBUG: - exception_reporter = debug.ExceptionReporter(context.get('request'), *sys.exc_info()) - return HttpResponse(exception_reporter.get_traceback_html(), status=500) - return None @@ -439,11 +431,18 @@ class APIView(View): response = exception_handler(exc, context) if response is None: - raise + self.raise_uncaught_exception(exc) response.exception = True return response + def raise_uncaught_exception(self, exc): + if settings.DEBUG: + renderer = self.request.accepted_renderer + use_plaintext_traceback = getattr(renderer, 'format') not in ('html', 'api') + self.request.force_plaintext_errors(use_plaintext_traceback) + raise + # Note: Views are made CSRF exempt from within `as_view` as to prevent # accidental removal of this exemption in cases where `dispatch` needs to # be overridden.