Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,4 @@ Contributors (chronological)
- Ben Windsor `@bwindsor <https://github.com/bwindsor>`_
- Kevin Kirsche `@kkirsche <https://github.com/kkirsche>`_
- Isira Seneviratne `@Isira-Seneviratne <https://github.com/Isira-Seneviratne>`_
- Dharanikumar Sekar `@dharani7998 <https://github.com/dharani7998>`_
4 changes: 2 additions & 2 deletions src/marshmallow/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ class MarshmallowHook:
) # type: Optional[Dict[Union[Tuple[str, bool], str], Any]]


def validates(field_name: str) -> Callable[..., Any]:
def validates(*field_names: str) -> Callable[..., Any]:
"""Register a field validator.

:param str field_name: Name of the field that the method validates.
"""
return set_hook(None, VALIDATES, field_name=field_name)
return set_hook(None, VALIDATES, field_names=field_names)
Comment thread
sloria marked this conversation as resolved.


def validates_schema(
Expand Down
59 changes: 30 additions & 29 deletions src/marshmallow/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1097,22 +1097,38 @@ def _invoke_field_validators(self, *, error_store: ErrorStore, data, many: bool)
for attr_name in self._hooks[VALIDATES]:
validator = getattr(self, attr_name)
validator_kwargs = validator.__marshmallow_hook__[VALIDATES]
field_name = validator_kwargs["field_name"]
field_names = validator_kwargs["field_names"]

try:
field_obj = self.fields[field_name]
except KeyError as error:
if field_name in self.declared_fields:
continue
raise ValueError(f'"{field_name}" field does not exist.') from error
for field_name in field_names:
try:
field_obj = self.fields[field_name]
except KeyError as error:
if field_name in self.declared_fields:
continue
raise ValueError(f'"{field_name}" field does not exist.') from error

data_key = (
field_obj.data_key if field_obj.data_key is not None else field_name
)
if many:
for idx, item in enumerate(data):
data_key = (
field_obj.data_key if field_obj.data_key is not None else field_name
)
if many:
for idx, item in enumerate(data):
try:
value = item[field_obj.attribute or field_name]
except KeyError:
pass
else:
validated_value = self._call_and_store(
getter_func=validator,
data=value,
field_name=data_key,
error_store=error_store,
index=(idx if self.opts.index_errors else None),
)
if validated_value is missing:
data[idx].pop(field_name, None)
else:
try:
value = item[field_obj.attribute or field_name]
value = data[field_obj.attribute or field_name]
except KeyError:
pass
else:
Expand All @@ -1121,24 +1137,9 @@ def _invoke_field_validators(self, *, error_store: ErrorStore, data, many: bool)
data=value,
field_name=data_key,
error_store=error_store,
index=(idx if self.opts.index_errors else None),
)
if validated_value is missing:
data[idx].pop(field_name, None)
else:
try:
value = data[field_obj.attribute or field_name]
except KeyError:
pass
else:
validated_value = self._call_and_store(
getter_func=validator,
data=value,
field_name=data_key,
error_store=error_store,
)
if validated_value is missing:
data.pop(field_name, None)
data.pop(field_name, None)

def _invoke_schema_validators(
self,
Expand Down