mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 16:40:03 +03:00
expose configurable allowing a default to be set on partial updates
This commit is contained in:
parent
8351747d98
commit
57968137fc
|
@ -48,7 +48,7 @@ Defaults to `True`.
|
|||
|
||||
If set, this gives the default value that will be used for the field if no input value is supplied. If not set the default behaviour is to not populate the attribute at all.
|
||||
|
||||
The `default` is not applied during partial update operations. In the partial update case only fields that are provided in the incoming data will have a validated value returned.
|
||||
The `default` is not applied during partial update operations, unless `set_default_if_partial` is set to True. In the typical path partial update case only fields that are provided in the incoming data will have a validated value returned.
|
||||
|
||||
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 `requires_context = True` attribute, then the serializer field will be passed as an argument.
|
||||
|
||||
|
@ -68,6 +68,12 @@ When serializing the instance, default will be used if the object attribute or d
|
|||
|
||||
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.
|
||||
|
||||
### set_default_if_partial
|
||||
|
||||
The `default` is not applied during partial update operations, unless `set_default_if_partial` is set to True. If set to True, the partial update will include the default value. Otherwise, partial updates will only apply to fields provided in the incoming data.
|
||||
|
||||
Note: This parameter is particularly useful for HiddenInput's with default values.
|
||||
|
||||
### `allow_null`
|
||||
|
||||
Normally an error will be raised if `None` is passed to a serializer field. Set this keyword argument to `True` if `None` should be considered a valid value.
|
||||
|
@ -542,7 +548,7 @@ For example, if `has_expired` was a property on the `Account` model, then the fo
|
|||
|
||||
## HiddenField
|
||||
|
||||
A field class that does not take a value based on user input, but instead takes its value from a default value or callable.
|
||||
A field class that does not take a value based on user input, but instead takes its value from a default value or callable. In the case of a partial update, the `default` value will not be applied unless `set_default_on_partial` is set to True for this field.
|
||||
|
||||
**Signature**: `HiddenField()`
|
||||
|
||||
|
|
|
@ -307,6 +307,7 @@ MISSING_ERROR_MESSAGE = (
|
|||
'ValidationError raised by `{class_name}`, but error key `{key}` does '
|
||||
'not exist in the `error_messages` dictionary.'
|
||||
)
|
||||
NO_DEFAULT_SET_ON_PARTIAL = 'May not enforce set_default_on_partial without setting a default value'
|
||||
|
||||
|
||||
class Field:
|
||||
|
@ -323,7 +324,7 @@ class Field:
|
|||
def __init__(self, read_only=False, write_only=False,
|
||||
required=None, default=empty, initial=empty, source=None,
|
||||
label=None, help_text=None, style=None,
|
||||
error_messages=None, validators=None, allow_null=False):
|
||||
error_messages=None, validators=None, allow_null=False, set_default_on_partial=False):
|
||||
self._creation_counter = Field._creation_counter
|
||||
Field._creation_counter += 1
|
||||
|
||||
|
@ -336,6 +337,7 @@ class Field:
|
|||
assert not (read_only and required), NOT_READ_ONLY_REQUIRED
|
||||
assert not (required and default is not empty), NOT_REQUIRED_DEFAULT
|
||||
assert not (read_only and self.__class__ == Field), USE_READONLYFIELD
|
||||
assert not (default is empty and set_default_on_partial), NO_DEFAULT_SET_ON_PARTIAL
|
||||
|
||||
self.read_only = read_only
|
||||
self.write_only = write_only
|
||||
|
@ -347,6 +349,7 @@ class Field:
|
|||
self.help_text = help_text
|
||||
self.style = {} if style is None else style
|
||||
self.allow_null = allow_null
|
||||
self.set_default_on_partial = set_default_on_partial
|
||||
|
||||
if self.default_empty_html is not empty:
|
||||
if default is not empty:
|
||||
|
@ -498,8 +501,11 @@ class Field:
|
|||
raise `SkipField`, indicating that no value should be set in the
|
||||
validated data for this field.
|
||||
"""
|
||||
if self.default is empty or getattr(self.root, 'partial', False):
|
||||
# No default, or this is a partial update.
|
||||
if self.default is empty or all([
|
||||
getattr(self.root, 'partial', False),
|
||||
not getattr(self.root, "set_default_on_partial", False)
|
||||
]):
|
||||
# No default, or this is a partial update where defaults are not set.
|
||||
raise SkipField()
|
||||
if callable(self.default):
|
||||
if hasattr(self.default, 'set_context'):
|
||||
|
|
|
@ -610,6 +610,18 @@ class TestDefaultInclusions:
|
|||
assert serializer.validated_data == {'integer': 456}
|
||||
assert serializer.errors == {}
|
||||
|
||||
def test_default_should_be_included_on_partial_update_when_set_default_on_partial_true(self):
|
||||
class ExampleSerializer(serializers.Serializer):
|
||||
char = serializers.CharField(default='abc', set_default_on_partial=True)
|
||||
integer = serializers.IntegerField()
|
||||
float = serializers.FloatField(required=False)
|
||||
|
||||
instance = MockObject(char='def', integer=123, float=4.2)
|
||||
serializer = ExampleSerializer(instance, data={'integer': 456})
|
||||
assert serializer.is_valid()
|
||||
assert serializer.validated_data == {'char': 'abc', 'integer': 456}
|
||||
assert serializer.errors == {}
|
||||
|
||||
|
||||
class TestSerializerValidationWithCompiledRegexField:
|
||||
def setup(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user