aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]docs/api-guide/authentication.md6
-rw-r--r--docs/topics/release-notes.md8
-rw-r--r--rest_framework/__init__.py2
-rw-r--r--rest_framework/generics.py1
-rw-r--r--rest_framework/mixins.py4
-rw-r--r--rest_framework/tests/generics.py42
-rw-r--r--rest_framework/views.py8
7 files changed, 63 insertions, 8 deletions
diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md
index 0eea31d7..1f08f542 100644..100755
--- a/docs/api-guide/authentication.md
+++ b/docs/api-guide/authentication.md
@@ -107,7 +107,7 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401
WWW-Authenticate: Basic realm="api"
-**Note:** If you use `BasicAuthentication` in production you must ensure that your API is only available over `https` only. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.
+**Note:** If you use `BasicAuthentication` in production you must ensure that your API is only available over `https`. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.
## TokenAuthentication
@@ -148,7 +148,7 @@ The `curl` command line tool may be useful for testing token authenticated APIs.
---
-**Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only.
+**Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https`.
---
@@ -259,7 +259,7 @@ Finally, sync your database.
---
-**Note:** If you use `OAuth2Authentication` in production you must ensure that your API is only available over `https` only.
+**Note:** If you use `OAuth2Authentication` in production you must ensure that your API is only available over `https`.
---
diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md
index d89bf80f..5e0aa098 100644
--- a/docs/topics/release-notes.md
+++ b/docs/topics/release-notes.md
@@ -40,6 +40,14 @@ You can determine your currently installed version using `pip freeze`:
## 2.2.x series
+### 2.2.7
+
+**Date**: 17th April 2013
+
+* Loud failure when view does not return a `Response` or `HttpResponse`.
+* Bugfix: Fix for Django 1.3 compatiblity.
+* Bugfix: Allow overridden `get_object()` to work correctly.
+
### 2.2.6
**Date**: 4th April 2013
diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py
index 7ac12058..856badc6 100644
--- a/rest_framework/__init__.py
+++ b/rest_framework/__init__.py
@@ -1,4 +1,4 @@
-__version__ = '2.2.6'
+__version__ = '2.2.7'
VERSION = __version__ # synonym
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index 36ecf915..f9133c73 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -130,6 +130,7 @@ class SingleObjectAPIView(SingleObjectMixin, GenericAPIView):
"""
Override default to add support for object-level permissions.
"""
+ queryset = self.filter_queryset(self.get_queryset())
obj = super(SingleObjectAPIView, self).get_object(queryset)
self.check_object_permissions(self.request, obj)
return obj
diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py
index 7d9a6e65..3bd7d6df 100644
--- a/rest_framework/mixins.py
+++ b/rest_framework/mixins.py
@@ -97,9 +97,7 @@ class RetrieveModelMixin(object):
Should be mixed in with `SingleObjectAPIView`.
"""
def retrieve(self, request, *args, **kwargs):
- queryset = self.get_queryset()
- filtered_queryset = self.filter_queryset(queryset)
- self.object = self.get_object(filtered_queryset)
+ self.object = self.get_object()
serializer = self.get_serializer(self.object)
return Response(serializer.data)
diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/generics.py
index f564890c..4a13389a 100644
--- a/rest_framework/tests/generics.py
+++ b/rest_framework/tests/generics.py
@@ -1,5 +1,6 @@
from __future__ import unicode_literals
from django.db import models
+from django.shortcuts import get_object_or_404
from django.test import TestCase
from rest_framework import generics, serializers, status
from rest_framework.tests.utils import RequestFactory
@@ -302,6 +303,47 @@ class TestInstanceView(TestCase):
self.assertEqual(new_obj.text, 'foobar')
+class TestOverriddenGetObject(TestCase):
+ """
+ Test cases for a RetrieveUpdateDestroyAPIView that does NOT use the
+ queryset/model mechanism but instead overrides get_object()
+ """
+ def setUp(self):
+ """
+ Create 3 BasicModel intances.
+ """
+ items = ['foo', 'bar', 'baz']
+ for item in items:
+ BasicModel(text=item).save()
+ self.objects = BasicModel.objects
+ self.data = [
+ {'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()
+ ]
+
+ class OverriddenGetObjectView(generics.RetrieveUpdateDestroyAPIView):
+ """
+ Example detail view for override of get_object().
+ """
+ model = BasicModel
+
+ def get_object(self):
+ pk = int(self.kwargs['pk'])
+ return get_object_or_404(BasicModel.objects.all(), id=pk)
+
+ self.view = OverriddenGetObjectView.as_view()
+
+ def test_overridden_get_object_view(self):
+ """
+ GET requests to RetrieveUpdateDestroyAPIView should return a single object.
+ """
+ request = factory.get('/1')
+ with self.assertNumQueries(1):
+ response = self.view(request, pk=1).render()
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, self.data[0])
+
+
# Regression test for #285
class CommentSerializer(serializers.ModelSerializer):
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 81cbdcbb..7c97607b 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -3,7 +3,7 @@ Provides an APIView class that is used as the base of all class-based views.
"""
from __future__ import unicode_literals
from django.core.exceptions import PermissionDenied
-from django.http import Http404
+from django.http import Http404, HttpResponse
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.views.decorators.csrf import csrf_exempt
@@ -327,6 +327,12 @@ class APIView(View):
"""
Returns the final response object.
"""
+ # Make the error obvious if a proper response is not returned
+ assert isinstance(response, HttpResponse), (
+ 'Expected a `Response` to be returned from the view, '
+ 'but received a `%s`' % type(response)
+ )
+
if isinstance(response, Response):
if not getattr(request, 'accepted_renderer', None):
neg = self.perform_content_negotiation(request, force=True)