Skip to content

Commit 6c0c69e

Browse files
Correct allow_null behaviour when required=False (#5888)
* Revert "Non-required fields with 'allow_null=True' should not imply a default value (#5639)" This reverts commit 905a557. Closes #5708 * Add test for allow_null + required=False Ref #5708: allow_null should imply default=None, even for non-required fields. * Re-order allow_null and default in field docs default is prior to allow_null. allow_null implies an outgoing default=None. * Adjust allow_null note.
1 parent c2b24f8 commit 6c0c69e

File tree

3 files changed

+16
-20
lines changed

3 files changed

+16
-20
lines changed

docs/api-guide/fields.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,6 @@ Setting this to `False` also allows the object attribute or dictionary key to be
4141

4242
Defaults to `True`.
4343

44-
### `allow_null`
45-
46-
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.
47-
48-
Note that setting this argument to `True` will imply a default value of `null` for serialization output, but does not imply a default for input deserialization.
49-
50-
Defaults to `False`
51-
5244
### `default`
5345

5446
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.
@@ -61,6 +53,14 @@ When serializing the instance, default will be used if the the object attribute
6153

6254
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.
6355

56+
### `allow_null`
57+
58+
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.
59+
60+
Note that, without an explicit `default`, setting this argument to `True` will imply a `default` value of `null` for serialization output, but does not imply a default for input deserialization.
61+
62+
Defaults to `False`
63+
6464
### `source`
6565

6666
The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `URLField(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `EmailField(source='user.email')`. When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal.

rest_framework/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,10 +442,10 @@ def get_attribute(self, instance):
442442
except (KeyError, AttributeError) as exc:
443443
if self.default is not empty:
444444
return self.get_default()
445-
if not self.required:
446-
raise SkipField()
447445
if self.allow_null:
448446
return None
447+
if not self.required:
448+
raise SkipField()
449449
msg = (
450450
'Got {exc_type} when attempting to get a value for field '
451451
'`{field}` on serializer `{serializer}`.\nThe serializer '

tests/test_serializer.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,6 @@ def create(self, validated_data):
384384
serializer.save()
385385
assert serializer.data == {'included': 'abc'}
386386

387-
def test_not_required_output_for_allow_null_field(self):
388-
class ExampleSerializer(serializers.Serializer):
389-
omitted = serializers.CharField(required=False, allow_null=True)
390-
included = serializers.CharField()
391-
392-
serializer = ExampleSerializer({'included': 'abc'})
393-
assert 'omitted' not in serializer.data
394-
395387

396388
class TestDefaultOutput:
397389
def setup(self):
@@ -486,12 +478,16 @@ class Serializer(serializers.Serializer):
486478
assert Serializer({'nested': {'a': '3', 'b': {'c': '4'}}}).data == {'nested': {'a': '3', 'c': '4'}}
487479

488480
def test_default_for_allow_null(self):
489-
# allow_null=True should imply default=None
481+
"""
482+
Without an explicit default, allow_null implies default=None when serializing. #5518 #5708
483+
"""
490484
class Serializer(serializers.Serializer):
491485
foo = serializers.CharField()
492486
bar = serializers.CharField(source='foo.bar', allow_null=True)
487+
optional = serializers.CharField(required=False, allow_null=True)
493488

494-
assert Serializer({'foo': None}).data == {'foo': None, 'bar': None}
489+
# allow_null=True should imply default=None when serialising:
490+
assert Serializer({'foo': None}).data == {'foo': None, 'bar': None, 'optional': None, }
495491

496492

497493
class TestCacheSerializerData:

0 commit comments

Comments
 (0)