diff options
| -rwxr-xr-x[-rw-r--r--] | docs/api-guide/authentication.md | 6 | ||||
| -rw-r--r-- | docs/topics/release-notes.md | 8 | ||||
| -rw-r--r-- | rest_framework/__init__.py | 2 | ||||
| -rw-r--r-- | rest_framework/generics.py | 1 | ||||
| -rw-r--r-- | rest_framework/mixins.py | 4 | ||||
| -rw-r--r-- | rest_framework/tests/generics.py | 42 | ||||
| -rw-r--r-- | rest_framework/views.py | 8 |
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) |
