Skip to content

Commit

Permalink
Now accepting as the required message anything that the ValidationErr…
Browse files Browse the repository at this point in the history
…or constructor takes
  • Loading branch information
0xDCA committed Jan 7, 2015
1 parent cb17377 commit 278ff69
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
9 changes: 7 additions & 2 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -236,18 +236,23 @@ Required Fields

You can make a field required by passing ``required=True``. An error will be stored if the the value is missing from the input to :meth:`Schema.load`.

Alternatively, you can provide a custom error message by passing ``required='My custom message'`` (and the required validation will be enabled as if ``required=True``)
Alternatively, you can provide a custom error message by passing ``required='My custom message'`` (and the required validation will be enabled when ``if required`` succeeds).
Dictionaries or lists are also accepted as the custom error message, in case you want to provide more information with the error.

.. code-block:: python
:emphasize-lines: 2,6
class UserSchema(Schema):
name = fields.String(required=True)
age = fields.Integer(required='Age is required.')
city = fields.String(required={'message': 'City required', 'code': 400})
email = fields.Email()
data, errors = UserSchema().load({'email': '[email protected]'})
errors # {'name': ['Missing data for required field.'], 'age': ['Age is required.']}
errors
# {'name': ['Missing data for required field.'],
# 'age': ['Age is required.'],
# 'city': {'message': 'City required', 'code': 400}}
Schema.validate
+++++++++++++++
Expand Down
13 changes: 8 additions & 5 deletions marshmallow/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,11 @@ class Field(FieldABC):
its only parameter and returns a boolean.
If it returns `False`, an :exc:`UnmarshallingError` is raised.
:param required: Raise an :exc:`UnmarshallingError` if the field value
is not supplied during deserialization. If it is a string, this validation
will be enabled and the provided string will be used as the error message
instead of the built in one.
is not supplied during deserialization. If it is not a bool, this validation
will be enabled when `if required` succeeds, and the provided value will be
used as the message of the ValidationError instead of the built in one.
In this case, message can be anything that the ValidationError constructor
accepts (a string, list or dict)
:param metadata: Extra arguments to be stored as metadata.
.. versionchanged:: 1.0.0
Expand Down Expand Up @@ -459,8 +461,9 @@ def deserialize(self, value):
def do_deserialization():
if value is missing:
if hasattr(self, 'required') and self.required:
message = (self.required if isinstance(self.required, basestring) else
'Missing data for required field.')
default_message = 'Missing data for required field.'
message = (default_message if isinstance(self.required, bool) else
self.required)
raise ValidationError(message)
output = self._deserialize(value)
self._validate(output)
Expand Down
12 changes: 7 additions & 5 deletions tests/test_deserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from marshmallow import fields, utils, Schema
from marshmallow.exceptions import UnmarshallingError, ValidationError
from marshmallow.compat import text_type, total_seconds
from marshmallow.compat import text_type, total_seconds, basestring

from tests.base import (
assert_almost_equal,
Expand Down Expand Up @@ -1031,13 +1031,15 @@ class ColorSchema(Schema):
assert data == {}


def test_required_message_can_be_changed():
message = 'My custom required message'

@pytest.mark.parametrize('message', ['My custom required message',
{'error': 'something', 'code': 400},
['first error', 'second error']])
def test_required_message_can_be_changed(message):
class RequireSchema(Schema):
age = fields.Integer(required=message)

user_data = {"name": "Phil"}
data, errs = RequireSchema().load(user_data)
assert message in errs['age']
expected = [message] if isinstance(message, basestring) else message
assert expected == errs['age']
assert data == {}

0 comments on commit 278ff69

Please sign in to comment.