Skip to content

Commit 29b4ab2

Browse files
author
Ryan P Kilby
committed
Nest ListField/DictField errors under the idx/key
1 parent c4132e5 commit 29b4ab2

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

rest_framework/fields.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,14 +1626,28 @@ def to_internal_value(self, data):
16261626
self.fail('not_a_list', input_type=type(data).__name__)
16271627
if not self.allow_empty and len(data) == 0:
16281628
self.fail('empty')
1629-
return [self.child.run_validation(item) for item in data]
1629+
return self.run_child_validation(data)
16301630

16311631
def to_representation(self, data):
16321632
"""
16331633
List of object instances -> List of dicts of primitive datatypes.
16341634
"""
16351635
return [self.child.to_representation(item) if item is not None else None for item in data]
16361636

1637+
def run_child_validation(self, data):
1638+
result = []
1639+
errors = {}
1640+
1641+
for idx, item in enumerate(data):
1642+
try:
1643+
result.append(self.child.run_validation(item))
1644+
except ValidationError as e:
1645+
errors[idx] = e.detail
1646+
1647+
if not errors:
1648+
return result
1649+
raise ValidationError(errors)
1650+
16371651

16381652
class DictField(Field):
16391653
child = _UnvalidatedField()
@@ -1669,10 +1683,7 @@ def to_internal_value(self, data):
16691683
data = html.parse_html_dict(data)
16701684
if not isinstance(data, dict):
16711685
self.fail('not_a_dict', input_type=type(data).__name__)
1672-
return {
1673-
six.text_type(key): self.child.run_validation(value)
1674-
for key, value in data.items()
1675-
}
1686+
return self.run_child_validation(data)
16761687

16771688
def to_representation(self, value):
16781689
"""
@@ -1683,6 +1694,22 @@ def to_representation(self, value):
16831694
for key, val in value.items()
16841695
}
16851696

1697+
def run_child_validation(self, data):
1698+
result = {}
1699+
errors = {}
1700+
1701+
for key, value in data.items():
1702+
key = six.text_type(key)
1703+
1704+
try:
1705+
result[key] = self.child.run_validation(value)
1706+
except ValidationError as e:
1707+
errors[key] = e.detail
1708+
1709+
if not errors:
1710+
return result
1711+
raise ValidationError(errors)
1712+
16861713

16871714
class JSONField(Field):
16881715
default_error_messages = {

tests/test_fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ class TestListField(FieldValues):
17671767
]
17681768
invalid_inputs = [
17691769
('not a list', ['Expected a list of items but got type "str".']),
1770-
([1, 2, 'error'], ['A valid integer is required.']),
1770+
([1, 2, 'error', 'error'], {2: ['A valid integer is required.'], 3: ['A valid integer is required.']}),
17711771
({'one': 'two'}, ['Expected a list of items but got type "dict".'])
17721772
]
17731773
outputs = [
@@ -1840,7 +1840,7 @@ class TestDictField(FieldValues):
18401840
({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}),
18411841
]
18421842
invalid_inputs = [
1843-
({'a': 1, 'b': None}, ['This field may not be null.']),
1843+
({'a': 1, 'b': None, 'c': None}, {'b': ['This field may not be null.'], 'c': ['This field may not be null.']}),
18441844
('not a dict', ['Expected a dictionary of items but got type "str".']),
18451845
]
18461846
outputs = [

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy