mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-05-26 01:03:12 +03:00
Allow required false and default (#4692)
* Default value will now be used when serializing if key or attribute is missing.
This commit is contained in:
parent
8a14b39e7d
commit
cf5d401a0e
|
@ -55,6 +55,8 @@ The `default` is not applied during partial update operations. In the partial up
|
||||||
|
|
||||||
May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `set_context` method, that will be called each time before getting the value with the field instance as only argument. This works the same way as for [validators](validators.md#using-set_context).
|
May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `set_context` method, that will be called each time before getting the value with the field instance as only argument. This works the same way as for [validators](validators.md#using-set_context).
|
||||||
|
|
||||||
|
When serializing the instance, default will be used if the the object attribute or dictionary key is not present in the instance.
|
||||||
|
|
||||||
Note that setting a `default` value implies that the field is not required. Including both the `default` and `required` keyword arguments is invalid and will raise an error.
|
Note that setting a `default` value implies that the field is not required. Including both the `default` and `required` keyword arguments is invalid and will raise an error.
|
||||||
|
|
||||||
### `source`
|
### `source`
|
||||||
|
|
|
@ -443,7 +443,9 @@ class Field(object):
|
||||||
try:
|
try:
|
||||||
return get_attribute(instance, self.source_attrs)
|
return get_attribute(instance, self.source_attrs)
|
||||||
except (KeyError, AttributeError) as exc:
|
except (KeyError, AttributeError) as exc:
|
||||||
if not self.required and self.default is empty:
|
if self.default is not empty:
|
||||||
|
return self.get_default()
|
||||||
|
if not self.required:
|
||||||
raise SkipField()
|
raise SkipField()
|
||||||
msg = (
|
msg = (
|
||||||
'Got {exc_type} when attempting to get a value for field '
|
'Got {exc_type} when attempting to get a value for field '
|
||||||
|
|
|
@ -372,36 +372,44 @@ class TestNotRequiredOutput:
|
||||||
serializer.save()
|
serializer.save()
|
||||||
assert serializer.data == {'included': 'abc'}
|
assert serializer.data == {'included': 'abc'}
|
||||||
|
|
||||||
def test_default_required_output_for_dict(self):
|
|
||||||
"""
|
|
||||||
'default="something"' should require dictionary key.
|
|
||||||
|
|
||||||
We need to handle this as the field will have an implicit
|
class TestDefaultOutput:
|
||||||
'required=False', but it should still have a value.
|
def setup(self):
|
||||||
"""
|
|
||||||
class ExampleSerializer(serializers.Serializer):
|
class ExampleSerializer(serializers.Serializer):
|
||||||
omitted = serializers.CharField(default='abc')
|
has_default = serializers.CharField(default='x')
|
||||||
included = serializers.CharField()
|
has_default_callable = serializers.CharField(default=lambda: 'y')
|
||||||
|
no_default = serializers.CharField()
|
||||||
|
self.Serializer = ExampleSerializer
|
||||||
|
|
||||||
serializer = ExampleSerializer({'included': 'abc'})
|
def test_default_used_for_dict(self):
|
||||||
with pytest.raises(KeyError):
|
|
||||||
serializer.data
|
|
||||||
|
|
||||||
def test_default_required_output_for_object(self):
|
|
||||||
"""
|
"""
|
||||||
'default="something"' should require object attribute.
|
'default="something"' should be used if dictionary key is missing from input.
|
||||||
|
|
||||||
We need to handle this as the field will have an implicit
|
|
||||||
'required=False', but it should still have a value.
|
|
||||||
"""
|
"""
|
||||||
class ExampleSerializer(serializers.Serializer):
|
serializer = self.Serializer({'no_default': 'abc'})
|
||||||
omitted = serializers.CharField(default='abc')
|
assert serializer.data == {'has_default': 'x', 'has_default_callable': 'y', 'no_default': 'abc'}
|
||||||
included = serializers.CharField()
|
|
||||||
|
|
||||||
instance = MockObject(included='abc')
|
def test_default_used_for_object(self):
|
||||||
serializer = ExampleSerializer(instance)
|
"""
|
||||||
with pytest.raises(AttributeError):
|
'default="something"' should be used if object attribute is missing from input.
|
||||||
serializer.data
|
"""
|
||||||
|
instance = MockObject(no_default='abc')
|
||||||
|
serializer = self.Serializer(instance)
|
||||||
|
assert serializer.data == {'has_default': 'x', 'has_default_callable': 'y', 'no_default': 'abc'}
|
||||||
|
|
||||||
|
def test_default_not_used_when_in_dict(self):
|
||||||
|
"""
|
||||||
|
'default="something"' should not be used if dictionary key is present in input.
|
||||||
|
"""
|
||||||
|
serializer = self.Serializer({'has_default': 'def', 'has_default_callable': 'ghi', 'no_default': 'abc'})
|
||||||
|
assert serializer.data == {'has_default': 'def', 'has_default_callable': 'ghi', 'no_default': 'abc'}
|
||||||
|
|
||||||
|
def test_default_not_used_when_in_object(self):
|
||||||
|
"""
|
||||||
|
'default="something"' should not be used if object attribute is present in input.
|
||||||
|
"""
|
||||||
|
instance = MockObject(has_default='def', has_default_callable='ghi', no_default='abc')
|
||||||
|
serializer = self.Serializer(instance)
|
||||||
|
assert serializer.data == {'has_default': 'def', 'has_default_callable': 'ghi', 'no_default': 'abc'}
|
||||||
|
|
||||||
|
|
||||||
class TestCacheSerializerData:
|
class TestCacheSerializerData:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user