diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 2efe89610..c5ad55668 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -100,7 +100,10 @@ def get_attribute(instance, attrs): if isinstance(instance, collections.Mapping): instance = instance[attr] else: - instance = getattr(instance, attr) + try: + instance = getattr(instance, attr) + except KeyError as exc: + raise ValueError('Exception raised in property attribute "{0}"; original exception was: {1}'.format(attr, exc)) except ObjectDoesNotExist: return None if is_simple_callable(instance): diff --git a/tests/test_serializer.py b/tests/test_serializer.py index cd82ba3df..5211a0c5a 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -344,6 +344,23 @@ class TestUnicodeRepr: class TestNotRequiredOutput: + def test_not_required_property_exception(self): + """ + A KeyError should propogate when it is thrown in a property attribute. + """ + class ExampleSerializer(serializers.Serializer): + raises_key_error = serializers.CharField(required=False) + + class ExampleObject: + @property + def raises_key_error(self): + raise KeyError() + + instance = ExampleObject() + serializer = ExampleSerializer(instance) + with pytest.raises(ValueError): + serializer.data + def test_not_required_output_for_dict(self): """ 'required=False' should allow a dictionary key to be missing in output.