Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field-level validation errors cannot be saved on a nested field with many=True #298

Closed
nelfin opened this issue Oct 14, 2015 · 0 comments
Closed
Labels

Comments

@nelfin
Copy link
Contributor

nelfin commented Oct 14, 2015

When validating a field, all of its error messages are saved and appended to the list of messages for that field name in call_and_store, but for fields.Nested with many=True the error messages for child elements of the collection are saved and stored in a dictionary keyed by the element index. This causes the following exception on this minimal test case:

class Inner(Schema):
    req = fields.Field(required=True)

class Outer(Schema):
    inner = fields.Nested(Inner, many=True)

    @validates('inner')
    def validates_inner(self, data):
        raise ValidationError('not a chance')

outer = Outer()
_, errors = outer.load({'inner': [{}]})
Traceback (most recent call last):
  File "/home/andrew/misc/marshmallow/tests/test_schema.py", line 1238, in test_all_errors_on_many_nested_field_with_validates_decorator
    _, errors = outer.load({'inner': [{}]})
  File "/home/andrew/misc/marshmallow/marshmallow/schema.py", line 539, in load
    result, errors = self._do_load(data, many, partial=partial, postprocess=True)
  File "/home/andrew/misc/marshmallow/marshmallow/schema.py", line 610, in _do_load
    self._invoke_field_validators(data=result, many=many)
  File "/home/andrew/misc/marshmallow/marshmallow/schema.py", line 789, in _invoke_field_validators
    field_obj=field_obj
  File "/home/andrew/misc/marshmallow/marshmallow/marshalling.py", line 74, in call_and_store
    errors.setdefault(field_name, []).extend(err.messages)
AttributeError: 'dict' object has no attribute 'extend'
nelfin added a commit to nelfin/marshmallow that referenced this issue Oct 14, 2015
Fixes marshmallow-code#298. When validating a field, all of its error messages are saved
and appended to the list of messages for that field name in
call_and_store, but for fields.Nested with many=True the error messages
for child elements of the collection are saved and stored in a
dictionary keyed by the element index.

This change introduces a _field key to the errors dictionary of a Nested
field for validation errors raised about the field as a whole, rather
than any one element. For example:

    >>> from marshmallow import (
    ...     fields, validates, Schema, ValidationError,
    ... )
    >>> class Inner(Schema):
    ...     x = fields.Int()
    ...
    >>> class Outer(Schema):
    ...     inner = fields.Nested(Inner, many=True)
    ...
    ...     @validates('inner')
    ...     def check_length(self, data):
    ...         if len(data) < 3:
    ...             raise ValidationError('Not enough elements.')
    ...
    >>> o = Outer()
    >>> _, errors = o.load({'inner': [{'x': 123}, {'x': 'abc'}]})
    >>> errors  # doctest: +NORMALIZE_WHITESPACE
    {'inner': {1: {'x': ['Not a valid integer.']},
              '_field': ['Not enough elements.']}}
@sloria sloria added the bug label Oct 14, 2015
@sloria sloria closed this as completed Oct 15, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants