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. 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.conf.urls.defaults import url, patterns, include
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from rest_framework import serializers, viewsets, routers from rest_framework import 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')
# ViewSets define the view behavior. # ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet): class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer fields = ('url', 'email', 'is_staff', 'groups')
class GroupViewSet(viewsets.ModelViewSet): class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all() 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 = routers.DefaultRouter()
router.register(r'users', UserViewSet, 'user') router.register(r'users', views.UserViewSet, name='user')
router.register(r'groups', GroupViewSet, 'group') router.register(r'groups', views.GroupViewSet, name='group')
# Wire up our API using automatic URL routing.
# Wire up our API URLs, letting the router do the hard work.
# Additionally, we include login URLs for the browseable API. # Additionally, we include login URLs for the browseable API.
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^', include(router.urls)), url(r'^', include(router.urls)),

View File

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

View File

@ -645,7 +645,7 @@ class ModelSerializer(Serializer):
for relation in reverse_rels: for relation in reverse_rels:
accessor_name = relation.get_accessor_name() 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 continue
related_model = relation.model related_model = relation.model
to_many = relation.field.rel.multiple to_many = relation.field.rel.multiple

View File

@ -344,6 +344,30 @@ class TestOverriddenGetObject(TestCase):
self.assertEqual(response.data, self.data[0]) 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 # Regression test for #285
class CommentSerializer(serializers.ModelSerializer): class CommentSerializer(serializers.ModelSerializer):