diff --git a/rest_framework/request.py b/rest_framework/request.py index b29e64d16..1527e435b 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -217,7 +217,8 @@ class Request: @property def data(self): if not _hasattr(self, '_full_data'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() return self._full_data @property @@ -420,13 +421,14 @@ class Request: _request = self.__getattribute__("_request") return getattr(_request, attr) except AttributeError: - return self.__getattribute__(attr) + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr}'") @property def POST(self): # Ensure that request.POST uses our request parsing. if not _hasattr(self, '_data'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() if is_form_media_type(self.content_type): return self._data return QueryDict('', encoding=self._request._encoding) @@ -437,7 +439,8 @@ class Request: # Different from the other two cases, which are not valid property # names on the WSGIRequest class. if not _hasattr(self, '_files'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() return self._files def force_plaintext_errors(self, value): diff --git a/tests/test_request.py b/tests/test_request.py index e37aa7dda..4263f2682 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -126,6 +126,25 @@ class TestContentParsing(TestCase): request.parsers = (PlainTextParser(), ) assert request.data == content + def test_calling_data_fails_when_attribute_error_is_raised(self): + """ + Ensure attribute errors raised when parsing are properly re-raised. + """ + expected_message = "Internal error" + + class BrokenParser: + media_type = "application/json" + + def parse(self, *args, **kwargs): + raise AttributeError(expected_message) + + http_request = factory.post('/', data={}, format="json") + request = Request(http_request) + request.parsers = (BrokenParser,) + + with self.assertRaisesMessage(WrappedAttributeError, expected_message): + request.data + class MockView(APIView): authentication_classes = (SessionAuthentication,)