diff --git a/rest_framework/response.py b/rest_framework/response.py index 0de01204d..53b5e15f6 100644 --- a/rest_framework/response.py +++ b/rest_framework/response.py @@ -20,9 +20,12 @@ class Response(SimpleTemplateResponse): """ super(Response, self).__init__(None, status=status) self.data = data - self.headers = headers and headers[:] or [] self.template_name = template_name self.exception = exception + + if headers: + for name,value in headers.iteritems(): + self[name] = value @property def rendered_content(self): diff --git a/rest_framework/tests/throttling.py b/rest_framework/tests/throttling.py index 0b94c25ba..4b98b9414 100644 --- a/rest_framework/tests/throttling.py +++ b/rest_framework/tests/throttling.py @@ -106,7 +106,7 @@ class ThrottlingTests(TestCase): if expect is not None: self.assertEquals(response['X-Throttle-Wait-Seconds'], expect) else: - self.assertFalse('X-Throttle-Wait-Seconds' in response.headers) + self.assertFalse('X-Throttle-Wait-Seconds' in response) def test_seconds_fields(self): """ diff --git a/rest_framework/tests/views.py b/rest_framework/tests/views.py index 43365e07a..13a70010d 100644 --- a/rest_framework/tests/views.py +++ b/rest_framework/tests/views.py @@ -1,11 +1,12 @@ import copy +from django.conf.urls.defaults import patterns, url from django.test import TestCase from django.test.client import RequestFactory from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.settings import api_settings -from rest_framework.views import APIView +from rest_framework.views import APIView, RedirectAPIView factory = RequestFactory() @@ -17,6 +18,16 @@ class BasicView(APIView): def post(self, request, *args, **kwargs): return Response({'method': 'POST', 'data': request.DATA}) +class RedirectBasicView(RedirectAPIView): + permanent = False + view_name = 'basic-view' + + +urlpatterns = patterns('', + url(r'^basic/$', BasicView.as_view(), name='basic-view'), + url(r'^redirect_to_basic/$', RedirectBasicView.as_view(), name='old-basic-view'), +) + @api_view(['GET', 'POST', 'PUT']) def basic_view(request): @@ -39,7 +50,7 @@ def sanitise_json_error(error_dict): return ret -class ClassBasedViewIntegrationTests(TestCase): +class ClassBasedViewIntegrationTests(TestCase): def setUp(self): self.view = BasicView.as_view() @@ -95,3 +106,16 @@ class FunctionBasedViewIntegrationTests(TestCase): } self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEquals(sanitise_json_error(response.data), expected) + +class RedirectViewTests(TestCase): + urls = 'rest_framework.tests.views' + + def setUp(self): + self.view = RedirectBasicView.as_view() + + def test_redirect(self): + request = factory.get('/redirect_to_basic', content_type='application/json') + response = self.view(request) + + self.assertEquals(response.status_code, status.HTTP_302_FOUND) + self.assertEquals(response['Location'], 'http://testserver/basic/') \ No newline at end of file diff --git a/rest_framework/views.py b/rest_framework/views.py index 1d3363c74..2d6647386 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -380,10 +380,11 @@ class RedirectAPIView(APIView): """ permanent = True view_name = None + #http_method_names = ['get', 'post', 'head', 'options', 'delete', 'put'] def get_redirect_url(self, request, *args, **kwargs): """ - Return the URL redirect to. Keyword arguments from the + Return the URL redirect to. Arguments and Keyword arguments from the URL pattern match generating the redirect request are provided as kwargs to this method. """ @@ -395,14 +396,30 @@ class RedirectAPIView(APIView): def get(self, request, *args, **kwargs): url = self.get_redirect_url(request, *args, **kwargs) if url: + headers = {'Location': url} if self.permanent: - return Response(status=status.HTTP_301_MOVED_PERMANENTLY) + return Response(status=status.HTTP_301_MOVED_PERMANENTLY, headers=headers) else: - return Response(status=status.HTTP_302_FOUND) + return Response(status=status.HTTP_302_FOUND, headers=headers) else: logger.warning('Gone: %s', self.request.path, extra={ - 'status_code': 410, + 'status_code': status.HTTP_410_GONE, 'request': self.request }) - return Response(status=status.HTTP_410_GONE) \ No newline at end of file + return Response(status=status.HTTP_410_GONE) + + def head(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs) + + def options(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs) + + def delete(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs) + + def put(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs)