fields shortcut on views

This commit is contained in:
Tom Christie 2013-04-29 13:20:15 +01:00
parent d17e2d852f
commit 53f9d4a380
4 changed files with 44 additions and 22 deletions

View File

@ -79,42 +79,35 @@ Let's take a look at a quick example of using REST framework to build a simple m
We'll create a read-write API for accessing users and groups.
Here's our `views.py` module:
from django.conf.urls.defaults import url, patterns, include
from django.contrib.auth.models import User, Group
from rest_framework import serializers, viewsets, routers
# Serializers control the representations your API exposes.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'email', 'is_staff', 'groups')
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ('url', 'name')
from rest_framework import viewsets, routers
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
fields = ('url', 'email', 'is_staff', 'groups')
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
fields = ('url', 'name')
And our `urls.py` setup:
from django.conf.urls.defaults import url, patterns, include
from myapp import views
from rest_framework import routers
# Routers provide a convienient way of automatically managing your URLs.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet, 'user')
router.register(r'groups', GroupViewSet, 'group')
router.register(r'users', views.UserViewSet, name='user')
router.register(r'groups', views.GroupViewSet, name='group')
# Wire up our API URLs, letting the router do the hard work.
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browseable API.
urlpatterns = patterns('',
url(r'^', include(router.urls)),

View File

@ -44,6 +44,10 @@ class GenericAPIView(views.APIView):
# the explicit style is generally preferred.
model = None
# This shortcut may be used instead of setting the `serializer_class`
# attribute, although using the explicit style is generally preferred.
fields = None
# If the `model` shortcut is used instead of `serializer_class`, then the
# serializer class will be constructed using this class as the base.
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
@ -193,6 +197,7 @@ class GenericAPIView(views.APIView):
class DefaultSerializer(self.model_serializer_class):
class Meta:
model = self.model
fields = self.fields
return DefaultSerializer
def get_queryset(self):

View File

@ -645,7 +645,7 @@ class ModelSerializer(Serializer):
for relation in reverse_rels:
accessor_name = relation.get_accessor_name()
if accessor_name not in self.opts.fields:
if not self.opts.fields or accessor_name not in self.opts.fields:
continue
related_model = relation.model
to_many = relation.field.rel.multiple

View File

@ -344,6 +344,30 @@ class TestOverriddenGetObject(TestCase):
self.assertEqual(response.data, self.data[0])
class TestFieldsShortcut(TestCase):
"""
Test cases for setting the `fields` attribute on a view.
"""
def setUp(self):
class OverriddenFieldsView(generics.RetrieveUpdateDestroyAPIView):
model = BasicModel
fields = ('text',)
class RegularView(generics.RetrieveUpdateDestroyAPIView):
model = BasicModel
self.overridden_fields_view = OverriddenFieldsView()
self.regular_view = RegularView()
def test_overridden_fields_view(self):
Serializer = self.overridden_fields_view.get_serializer_class()
self.assertEqual(Serializer().fields.keys(), ['text'])
def test_not_overridden_fields_view(self):
Serializer = self.regular_view.get_serializer_class()
self.assertEqual(Serializer().fields.keys(), ['id', 'text'])
# Regression test for #285
class CommentSerializer(serializers.ModelSerializer):