diff --git a/djangorestframework/response.py b/djangorestframework/response.py index be2c3ebe4..a352531f8 100644 --- a/djangorestframework/response.py +++ b/djangorestframework/response.py @@ -53,6 +53,14 @@ class Response(SimpleTemplateResponse): if renderers is not None: self.renderers = renderers + def render(self): + #TODO: see ImmediateResponse + try: + return super(Response, self).render() + except ImmediateResponse as response: + response.renderers = self.renderers + return response.render() + @property def rendered_content(self): """ @@ -166,6 +174,18 @@ class ImmediateResponse(Response, Exception): """ A subclass of :class:`Response` used to abort the current request handling. """ + #TODO: this is just a temporary fix, the whole rendering/support for ImmediateResponse, should be remade : see issue #163 + + def render(self): + try: + return super(Response, self).render() + except ImmediateResponse as exc: + renderer, media_type = self._determine_renderer() + self.renderers.remove(renderer) + if len(self.renderers) == 0: + raise RuntimeError('Caught an ImmediateResponse while '\ + 'trying to render an ImmediateResponse') + return self.render() def __str__(self): """ diff --git a/djangorestframework/tests/mixins.py b/djangorestframework/tests/mixins.py index 85c95d61c..25c57bd6e 100644 --- a/djangorestframework/tests/mixins.py +++ b/djangorestframework/tests/mixins.py @@ -281,6 +281,6 @@ class TestPagination(TestCase): paginated URLs. So page 1 should contain ?page=2, not ?page=1&page=2 """ request = self.req.get('/paginator/?page=1') response = MockPaginatorView.as_view()(request) - content = json.loads(response.content) + content = response.raw_content self.assertTrue('page=2' in content['next']) self.assertFalse('page=1' in content['next']) diff --git a/djangorestframework/tests/response.py b/djangorestframework/tests/response.py index 956036801..ccf6de345 100644 --- a/djangorestframework/tests/response.py +++ b/djangorestframework/tests/response.py @@ -95,21 +95,56 @@ class TestResponseDetermineRenderer(TestCase): class TestResponseRenderContent(TestCase): - def get_response(self, url='', accept_list=[], content=None): + def get_response(self, url='', accept_list=[], content=None, + renderer_classes=DEFAULT_RENDERERS): + accept_list = accept_list[0:] request = RequestFactory().get(url, HTTP_ACCEPT=','.join(accept_list)) - return Response(request=request, content=content, renderers=[r() for r in DEFAULT_RENDERERS]) + return Response(request=request, content=content, + renderers=[r() for r in renderer_classes]) def test_render(self): """ - Test rendering simple data to json. + Test rendering simple data to json. """ content = {'a': 1, 'b': [1, 2, 3]} content_type = 'application/json' response = self.get_response(accept_list=[content_type], content=content) - response.render() + response = response.render() self.assertEqual(json.loads(response.content), content) self.assertEqual(response['Content-Type'], content_type) + def test_render_no_renderer(self): + """ + Test rendering response when no renderer can satisfy accept. + """ + content = 'bla' + content_type = 'weirdcontenttype' + response = self.get_response(accept_list=[content_type], content=content) + response = response.render() + self.assertEqual(response.status_code, 406) + self.assertIsNotNone(response.content) + + def test_render_renderer_raises_ImmediateResponse(self): + """ + Test rendering response when renderer raises ImmediateResponse + """ + class PickyJSONRenderer(BaseRenderer): + """ + A renderer that doesn't make much sense, just to try + out raising an ImmediateResponse + """ + media_type = 'application/json' + def render(self, obj=None, media_type=None): + raise ImmediateResponse({'error': '!!!'}, status=400) + + response = self.get_response( + accept_list=['application/json'], + renderer_classes=[PickyJSONRenderer, JSONRenderer] + ) + response = response.render() + self.assertEqual(response.status_code, 400) + self.assertEqual(response.content, json.dumps({'error': '!!!'})) + DUMMYSTATUS = status.HTTP_200_OK DUMMYCONTENT = 'dummycontent'