Skip to content

Commit

Permalink
Merge pull request #9 from ployst/carles/serializer-builder
Browse files Browse the repository at this point in the history
Add SerializerBuilder
  • Loading branch information
alexcouper committed Apr 1, 2016
2 parents aec4646 + 984a8c3 commit 6fa99c3
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 7 deletions.
39 changes: 34 additions & 5 deletions drfutils/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ def get_querystring_fields(serializer, arg_name):
return None


class DynamicFieldsSerializerMixin(object):
class FieldLimiterMixin(object):
def keep_only_fields(self, fields):
if fields is not None:
existing = set(self.fields.keys())
for field_name in existing - fields:
self.fields.pop(field_name)


class DynamicFieldsSerializerMixin(FieldLimiterMixin):
"""
Limit the number of fields to be retrieved as per request querystring.
Expand All @@ -35,11 +43,22 @@ def __init__(self, *args, **kwargs):
"""
super().__init__(*args, **kwargs)
fields = get_querystring_fields(self, 'fields')
self.keep_only_fields(fields)

if fields is not None:
existing = set(self.fields.keys())
for field_name in existing - fields:
self.fields.pop(field_name)

class LimitedFieldsSerializerMixin(FieldLimiterMixin):
"""
Limit the number of fields to be retrieved to Meta.only_fields
"""
def __init__(self, *args, **kwargs):
"""
Change the subset of fields to display based on only_fields
"""
super().__init__(*args, **kwargs)
fields = set(self.Meta.only_fields)
self.keep_only_fields(fields)


class ExpandableFieldsSerializerMixin(object):
Expand Down Expand Up @@ -68,3 +87,13 @@ def __init__(self, *args, **kwargs):
self.fields[field_name] = serializer_class(
context=self.context
)


def SubSerializer(serializer_class, fields):
serializer_class = type(
'Sub{}'.format(serializer_class.__name__),
(LimitedFieldsSerializerMixin, serializer_class),
{}
)
serializer_class.Meta.only_fields = fields
return serializer_class
31 changes: 29 additions & 2 deletions drfutils/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
from ..serializers import (
DynamicFieldsSerializerMixin,
ExpandableFieldsSerializerMixin,
SubSerializer,
)


class CreatorSerializer(serializers.Serializer):
name = fields.CharField()
other = serializers.SerializerMethodField()
nickname = fields.CharField()

class Meta:
fields = ('name', 'nickname', 'other')

def get_other(self, *args):
return 'field in expansion'
Expand All @@ -30,7 +35,7 @@ class TestExpandableFieldsSerializer(TestCase):
def test_expands_requested_fields(self):

class ThingWithCreator(object):
creator = {'name': '[email protected]'}
creator = {'name': '[email protected]', 'nickname': 'jim'}

request = Mock()
request.query_params.get.return_value = 'creator'
Expand All @@ -40,7 +45,11 @@ class ThingWithCreator(object):

self.assertDictEqual(
serializer.data['creator'],
{'name': '[email protected]', 'other': 'field in expansion'}
{
'name': '[email protected]',
'nickname': 'jim',
'other': 'field in expansion'
}
)

def test_does_not_expand_by_default(self):
Expand Down Expand Up @@ -105,3 +114,21 @@ class Thing(object):
self.assertDictEqual(
serializer.data, {'name': 'Jane', 'nickname': 'thesnake'}
)


class TestSerializerBuilder(TestCase):

def test_only_returns_requested_fields(self):
serializer_class = SubSerializer(CreatorSerializer, ('nickname',))
self.assertDictEqual(serializer_class.name, 'SubCreatorSerializer')

def test_only_returns_requested_fields(self):
class Thing(object):
name = 'Only James'
nickname = 'catnip'

jim = Thing()
serializer_class = SubSerializer(CreatorSerializer, ('nickname',))
serializer = serializer_class(jim)

self.assertDictEqual(serializer.data, {'nickname': 'catnip'})

0 comments on commit 6fa99c3

Please sign in to comment.