diff options
| -rw-r--r-- | docs/topics/release-notes.md | 5 | ||||
| -rw-r--r-- | rest_framework/__init__.py | 2 | ||||
| -rw-r--r-- | rest_framework/permissions.py | 5 | ||||
| -rw-r--r-- | rest_framework/routers.py | 17 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 8 | ||||
| -rw-r--r-- | rest_framework/tests/serializer.py | 18 |
6 files changed, 45 insertions, 10 deletions
diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 5777b82d..e7d62721 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,12 +40,15 @@ You can determine your currently installed version using `pip freeze`: ## 2.3.x series -### Master +### 2.3.2 + +**Date**: 16th May 2013 * Added SearchFilter * Added OrderingFilter * Added GenericViewSet * Bugfix: Multiple `@action` and `@link` methods now allowed on viewsets. +* Bugfix: Fix API Root view issue with DjangoModelPermissions ### 2.3.2 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index b4961e2f..0b1e67fb 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -1,4 +1,4 @@ -__version__ = '2.3.2' +__version__ = '2.3.3' VERSION = __version__ # synonym diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 751f31a7..45fcfd66 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -126,6 +126,11 @@ class DjangoModelPermissions(BasePermission): if model_cls is None and queryset is not None: model_cls = queryset.model + # Workaround to ensure DjangoModelPermissions are not applied + # to the root view when using DefaultRouter. + if model_cls is None and getattr(view, '_ignore_model_permissions'): + return True + assert model_cls, ('Cannot apply DjangoModelPermissions on a view that' ' does not have `.model` or `.queryset` property.') diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 76714fd0..dba104c3 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -16,6 +16,7 @@ For example, you might have a `urls.py` that looks something like this: from __future__ import unicode_literals from collections import namedtuple +from rest_framework import views from rest_framework.compat import patterns, url from rest_framework.decorators import api_view from rest_framework.response import Response @@ -217,14 +218,16 @@ class DefaultRouter(SimpleRouter): for prefix, viewset, basename in self.registry: api_root_dict[prefix] = list_name.format(basename=basename) - @api_view(('GET',)) - def api_root(request, format=None): - ret = {} - for key, url_name in api_root_dict.items(): - ret[key] = reverse(url_name, request=request, format=format) - return Response(ret) + class APIRoot(views.APIView): + _ignore_model_permissions = True - return api_root + def get(self, request, format=None): + ret = {} + for key, url_name in api_root_dict.items(): + ret[key] = reverse(url_name, request=request, format=format) + return Response(ret) + + return APIRoot.as_view() def get_urls(self): """ diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index ecff2c52..7707de7a 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -649,8 +649,14 @@ class ModelSerializer(Serializer): # Add the `read_only` flag to any fields that have bee specified # in the `read_only_fields` option for field_name in self.opts.read_only_fields: + assert field_name not in self.base_fields.keys(), \ + "field '%s' on serializer '%s' specfied in " \ + "`read_only_fields`, but also added " \ + "as an explict field. Remove it from `read_only_fields`." % \ + (field_name, self.__class__.__name__) assert field_name in ret, \ - "read_only_fields on '%s' included invalid item '%s'" % \ + "Noexistant field '%s' specified in `read_only_fields` " \ + "on serializer '%s'." % \ (self.__class__.__name__, field_name) ret[field_name].read_only = True diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 84e1ee4e..db3881f9 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -78,6 +78,18 @@ class PersonSerializer(serializers.ModelSerializer): read_only_fields = ('age',) +class PersonSerializerInvalidReadOnly(serializers.ModelSerializer): + """ + Testing for #652. + """ + info = serializers.Field(source='info') + + class Meta: + model = Person + fields = ('name', 'age', 'info') + read_only_fields = ('age', 'info') + + class AlbumsSerializer(serializers.ModelSerializer): class Meta: @@ -189,6 +201,12 @@ class BasicTests(TestCase): # Assert age is unchanged (35) self.assertEqual(instance.age, self.person_data['age']) + def test_invalid_read_only_fields(self): + """ + Regression test for #652. + """ + self.assertRaises(AssertionError, PersonSerializerInvalidReadOnly, []) + class DictStyleSerializer(serializers.Serializer): """ |
