-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Closed
Description
Checklist
- I have verified that that issue exists against the
master
branch of Django REST framework. - I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- This is not a usage question. (Those should be directed to the discussion group instead.)
- This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
- I have reduced the issue to the simplest possible case.
- I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)
Steps to reproduce
- Create a Serializer with a nested Serializer, e.g.:
class MySerializer(Serializer):
payload = PayloadSerializer(default={}, write_only=True)
class PayloadSerializer(Serializer):
some_field = CharField()
- Post a malformed payload that is not a dictionary:
{
"payload": 1
}
Expected behavior
Nested Serializer should fail and throw a ValidationError, Browsable API should render empty fields.
Actual behavior
Server crashes in serializer_helpers.py at in as_form_field because integer is not iterable:
def as_form_field(self):
values = {}
for key, value in self.value.items():
if isinstance(value, (list, dict)):
values[key] = value
else:
values[key] = '' if (value is None or value is False) else force_str(value)
return self.__class__(self._field, values, self.errors, self._prefix)
My workaround, modify Parent serializer:
class PayloadNestedField(NestedBoundField):
def __init__(self, field, value, errors, prefix=''):
if value is not None and not isinstance(value, dict):
value = {}
super().__init__(field, value, errors, prefix)
class PayloadSerializer(Serializer):
some_field = CharField()
def __getitem__(self, key):
field = self.fields[key]
value = self.data.get(key)
error = self.errors.get(key) if hasattr(self, '_errors') else None
if key == 'payload':
return PayloadNestedField(field, value, error)
else:
return super().__getitem__(key)
I think the issue here is that NestedBoundField only defaults the value to {} if it is None or the empty string here:
class NestedBoundField(BoundField):
"""
This `BoundField` additionally implements __iter__ and __getitem__
in order to support nested bound fields. This class is the type of
`BoundField` that is used for serializer fields.
"""
def __init__(self, field, value, errors, prefix=''):
if value is None or value == '':
value = {}
super().__init__(field, value, errors, prefix)
Metadata
Metadata
Assignees
Labels
No labels