From 2e24eae49ab0ee230e865ffe87baa47cda1b09c3 Mon Sep 17 00:00:00 2001 From: Omar Khan Date: Fri, 9 Oct 2015 07:37:26 +0700 Subject: [PATCH] Serialize mapping attributes --- rest_framework/fields.py | 9 ++++++++- tests/test_serializer.py | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 0d4a51152..6b7aa1fc3 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -75,7 +75,14 @@ def get_attribute(instance, attrs): return None try: if isinstance(instance, collections.Mapping): - instance = instance[attr] + try: + instance = instance[attr] + except KeyError as keyerror: + # Does the mapping has a method or property with that name? + try: + instance = getattr(instance, attr) + except AttributeError: + raise keyerror else: instance = getattr(instance, attr) except ObjectDoesNotExist: diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 741c6ab17..5d43b2622 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -309,3 +309,28 @@ class TestCacheSerializerData: pickled = pickle.dumps(serializer.data) data = pickle.loads(pickled) assert data == {'field1': 'a', 'field2': 'b'} + + +class TestMapping: + def setup(self): + class ExampleSerializer(serializers.Serializer): + entries = serializers.ListField() + last_entry = serializers.CharField() + self.Serializer = ExampleSerializer + self.data = {'entries': ['a', 'b', 'c']} + self.expected = {'entries': ['a', 'b', 'c'], 'last_entry': 'c'} + + def test_mapping_with_method(self): + class Mapping(dict): + def last_entry(self): + return self['entries'][-1] + serializer = self.Serializer(Mapping(self.data)) + assert serializer.data == self.expected + + def test_mapping_with_property(self): + class Mapping(dict): + @property + def last_entry(self): + return self['entries'][-1] + serializer = self.Serializer(Mapping(self.data)) + assert serializer.data == self.expected