mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-10 19:56:59 +03:00
Dict field allow empty (#6583)
* dict field: support allow_empty option * document ListField allow_empty option * document HStoreField allow_empty parameter
This commit is contained in:
parent
564faddb0f
commit
a7c577cb31
|
@ -448,9 +448,10 @@ Requires either the `Pillow` package or `PIL` package. The `Pillow` package is
|
|||
|
||||
A field class that validates a list of objects.
|
||||
|
||||
**Signature**: `ListField(child=<A_FIELD_INSTANCE>, min_length=None, max_length=None)`
|
||||
**Signature**: `ListField(child=<A_FIELD_INSTANCE>, allow_empty=True, min_length=None, max_length=None)`
|
||||
|
||||
- `child` - A field instance that should be used for validating the objects in the list. If this argument is not provided then objects in the list will not be validated.
|
||||
- `allow_empty` - Designates if empty lists are allowed.
|
||||
- `min_length` - Validates that the list contains no fewer than this number of elements.
|
||||
- `max_length` - Validates that the list contains no more than this number of elements.
|
||||
|
||||
|
@ -471,9 +472,10 @@ We can now reuse our custom `StringListField` class throughout our application,
|
|||
|
||||
A field class that validates a dictionary of objects. The keys in `DictField` are always assumed to be string values.
|
||||
|
||||
**Signature**: `DictField(child=<A_FIELD_INSTANCE>)`
|
||||
**Signature**: `DictField(child=<A_FIELD_INSTANCE>, allow_empty=True)`
|
||||
|
||||
- `child` - A field instance that should be used for validating the values in the dictionary. If this argument is not provided then values in the mapping will not be validated.
|
||||
- `allow_empty` - Designates if empty dictionaries are allowed.
|
||||
|
||||
For example, to create a field that validates a mapping of strings to strings, you would write something like this:
|
||||
|
||||
|
@ -488,9 +490,10 @@ You can also use the declarative style, as with `ListField`. For example:
|
|||
|
||||
A preconfigured `DictField` that is compatible with Django's postgres `HStoreField`.
|
||||
|
||||
**Signature**: `HStoreField(child=<A_FIELD_INSTANCE>)`
|
||||
**Signature**: `HStoreField(child=<A_FIELD_INSTANCE>, allow_empty=True)`
|
||||
|
||||
- `child` - A field instance that is used for validating the values in the dictionary. The default child field accepts both empty strings and null values.
|
||||
- `allow_empty` - Designates if empty dictionaries are allowed.
|
||||
|
||||
Note that the child field **must** be an instance of `CharField`, as the hstore extension stores values as strings.
|
||||
|
||||
|
|
|
@ -1663,11 +1663,13 @@ class DictField(Field):
|
|||
child = _UnvalidatedField()
|
||||
initial = {}
|
||||
default_error_messages = {
|
||||
'not_a_dict': _('Expected a dictionary of items but got type "{input_type}".')
|
||||
'not_a_dict': _('Expected a dictionary of items but got type "{input_type}".'),
|
||||
'empty': _('This dictionary may not be empty.'),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
||||
self.allow_empty = kwargs.pop('allow_empty', True)
|
||||
|
||||
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
||||
assert self.child.source is None, (
|
||||
|
@ -1693,6 +1695,9 @@ class DictField(Field):
|
|||
data = html.parse_html_dict(data)
|
||||
if not isinstance(data, dict):
|
||||
self.fail('not_a_dict', input_type=type(data).__name__)
|
||||
if not self.allow_empty and len(data) == 0:
|
||||
self.fail('empty')
|
||||
|
||||
return self.run_child_validation(data)
|
||||
|
||||
def to_representation(self, value):
|
||||
|
|
|
@ -1982,6 +1982,7 @@ class TestDictField(FieldValues):
|
|||
"""
|
||||
valid_inputs = [
|
||||
({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}),
|
||||
({}, {}),
|
||||
]
|
||||
invalid_inputs = [
|
||||
({'a': 1, 'b': None, 'c': None}, {'b': ['This field may not be null.'], 'c': ['This field may not be null.']}),
|
||||
|
@ -2009,6 +2010,16 @@ class TestDictField(FieldValues):
|
|||
output = field.run_validation(None)
|
||||
assert output is None
|
||||
|
||||
def test_allow_empty_disallowed(self):
|
||||
"""
|
||||
If allow_empty is False then an empty dict is not a valid input.
|
||||
"""
|
||||
field = serializers.DictField(allow_empty=False)
|
||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||
field.run_validation({})
|
||||
|
||||
assert exc_info.value.detail == ['This dictionary may not be empty.']
|
||||
|
||||
|
||||
class TestNestedDictField(FieldValues):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user