Nest ListField/DictField errors under the idx/key

This commit is contained in:
Ryan P Kilby 2017-12-04 23:47:12 -05:00
parent 634c0f9788
commit 3fee0bf574
2 changed files with 34 additions and 7 deletions

View File

@ -1626,7 +1626,7 @@ class ListField(Field):
self.fail('not_a_list', input_type=type(data).__name__) self.fail('not_a_list', input_type=type(data).__name__)
if not self.allow_empty and len(data) == 0: if not self.allow_empty and len(data) == 0:
self.fail('empty') self.fail('empty')
return [self.child.run_validation(item) for item in data] return self.run_child_validation(data)
def to_representation(self, data): def to_representation(self, data):
""" """
@ -1634,6 +1634,20 @@ class ListField(Field):
""" """
return [self.child.to_representation(item) if item is not None else None for item in data] return [self.child.to_representation(item) if item is not None else None for item in data]
def run_child_validation(self, data):
result = []
errors = OrderedDict()
for idx, item in enumerate(data):
try:
result.append(self.child.run_validation(item))
except ValidationError as e:
errors[idx] = e.detail
if not errors:
return result
raise ValidationError(errors)
class DictField(Field): class DictField(Field):
child = _UnvalidatedField() child = _UnvalidatedField()
@ -1669,10 +1683,7 @@ class DictField(Field):
data = html.parse_html_dict(data) data = html.parse_html_dict(data)
if not isinstance(data, dict): if not isinstance(data, dict):
self.fail('not_a_dict', input_type=type(data).__name__) self.fail('not_a_dict', input_type=type(data).__name__)
return { return self.run_child_validation(data)
six.text_type(key): self.child.run_validation(value)
for key, value in data.items()
}
def to_representation(self, value): def to_representation(self, value):
""" """
@ -1683,6 +1694,22 @@ class DictField(Field):
for key, val in value.items() for key, val in value.items()
} }
def run_child_validation(self, data):
result = {}
errors = OrderedDict()
for key, value in data.items():
key = six.text_type(key)
try:
result[key] = self.child.run_validation(value)
except ValidationError as e:
errors[key] = e.detail
if not errors:
return result
raise ValidationError(errors)
class JSONField(Field): class JSONField(Field):
default_error_messages = { default_error_messages = {

View File

@ -1767,7 +1767,7 @@ class TestListField(FieldValues):
] ]
invalid_inputs = [ invalid_inputs = [
('not a list', ['Expected a list of items but got type "str".']), ('not a list', ['Expected a list of items but got type "str".']),
([1, 2, 'error'], ['A valid integer is required.']), ([1, 2, 'error', 'error'], {2: ['A valid integer is required.'], 3: ['A valid integer is required.']}),
({'one': 'two'}, ['Expected a list of items but got type "dict".']) ({'one': 'two'}, ['Expected a list of items but got type "dict".'])
] ]
outputs = [ outputs = [
@ -1840,7 +1840,7 @@ class TestDictField(FieldValues):
({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}), ({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}),
] ]
invalid_inputs = [ invalid_inputs = [
({'a': 1, 'b': None}, ['This field may not be null.']), ({'a': 1, 'b': None, 'c': None}, {'b': ['This field may not be null.'], 'c': ['This field may not be null.']}),
('not a dict', ['Expected a dictionary of items but got type "str".']), ('not a dict', ['Expected a dictionary of items but got type "str".']),
] ]
outputs = [ outputs = [