This commit is contained in:
Ludwig Kraatz 2012-12-12 12:30:18 -08:00
commit 368b769977
3 changed files with 97 additions and 1 deletions

View File

@ -213,3 +213,23 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
class RedirectAPIView(mixins.RedirectMixin,
GenericAPIView):
"""
Redirect View used to redirect requests to a different/moved endpoint
"""
def get(self, request, *args, **kwargs):
return self.redirect(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.redirect(request, *args, **kwargs)
def options(self, request, *args, **kwargs):
return self.redirect(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.redirect(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.redirect(request, *args, **kwargs)

View File

@ -7,6 +7,7 @@ which allows mixin classes to be composed in interesting ways.
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.reverse import reverse
class CreateModelMixin(object):
@ -123,3 +124,42 @@ class DestroyModelMixin(object):
self.object = self.get_object()
self.object.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class RedirectMixin(object):
"""
A Mixin that provides a redirect method,
redirecting to a different resource endpoint
"""
redirect_permanent = True
redirect_with_query_string = True
redirect_to_view_name = None
redirect_to_url = None
def get_redirect_url(self, request, *args, **kwargs):
"""
Returning where to redirect to.
To url, view-name or nowhere
"""
if self.redirect_to_url:
url = self.redirect_to_url % kwargs
else:
try:
url = reverse(self.redirect_view_name, args=args, kwargs=kwargs, request=request)
except:
return None
query_string = self.request.META.get('QUERY_STRING', '')
if query_string and self.redirect_with_query_string:
url = '%(url)s?%(query_string)s' % {'url': url, 'query_string': query_string}
return url
def redirect(self, request, *args, **kwargs):
url = self.get_redirect_url(request, *args, **kwargs)
if url:
headers = {'Location': url}
if self.redirect_permanent:
return Response(status=status.HTTP_301_MOVED_PERMANENTLY, headers=headers)
else:
return Response(status=status.HTTP_302_FOUND, headers=headers)
else:
return Response(status=status.HTTP_410_GONE)

View File

@ -1,4 +1,5 @@
from django.test import TestCase
from django.conf.urls.defaults import patterns, url
from django.test.client import RequestFactory
from django.utils import simplejson as json
from rest_framework import generics, serializers, status
@ -14,13 +15,19 @@ class RootView(generics.ListCreateAPIView):
"""
model = BasicModel
class InstanceView(generics.RetrieveUpdateDestroyAPIView):
"""
Example description for OPTIONS.
"""
model = BasicModel
class RedirectToRootView(generics.RedirectAPIView):
redirect_permanent = False
redirect_view_name = 'root-view'
class RedirectToURL(generics.RedirectAPIView):
redirect_to_url = 'http://foo.bar'
redirect_with_query_string = False
class SlugSerializer(serializers.ModelSerializer):
slug = serializers.Field() # read only
@ -38,6 +45,10 @@ class SlugBasedInstanceView(InstanceView):
serializer_class = SlugSerializer
urlpatterns = patterns('',
url(r'^root/$', RootView.as_view(), name='root-view'),
)
class TestRootView(TestCase):
def setUp(self):
"""
@ -301,3 +312,28 @@ class TestCreateModelWithAutoNowAddField(TestCase):
self.assertEquals(response.status_code, status.HTTP_201_CREATED)
created = self.objects.get(id=1)
self.assertEquals(created.content, 'foobar')
class RedirectViewTests(TestCase):
urls = 'rest_framework.tests.generics'
def test_redirect(self):
request = factory.get('/redirect_to_root/?foo=bar')
response = RedirectToRootView.as_view()(request)
self.assertEquals(response.status_code, status.HTTP_302_FOUND)
self.assertEquals(response['Location'], 'http://testserver/root/?foo=bar')
def test_redirect_to_nowhere(self):
request = factory.get('/redirect_to_nowhere/')
response = generics.RedirectAPIView.as_view()(request)
self.assertEquals(response.status_code, status.HTTP_410_GONE)
def test_redirect_to_url(self):
request = factory.get('/redirect_to_url/?foo=bar')
response = RedirectToURL.as_view()(request)
self.assertEquals(response.status_code, status.HTTP_301_MOVED_PERMANENTLY)
self.assertEquals(response['Location'], 'http://foo.bar')