Skip to content

Commit 6221124

Browse files
Ryan P KilbyCarlton Gibson
authored andcommitted
Docs about default value for dotted source, additional tests (#5489)
* Add docs note on dotted source + default value * Add additional dotted source tests
1 parent 5d7b6e5 commit 6221124

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

docs/api-guide/fields.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Note that setting a `default` value implies that the field is not required. Incl
6161

6262
### `source`
6363

64-
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')`.
64+
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.
6565

6666
The value `source='*'` has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation.
6767

tests/test_serializer.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,31 @@ class Serializer(serializers.Serializer):
424424

425425
assert Serializer({'traversed': {'attr': 'abc'}}).data == {'traversed': 'abc'}
426426

427+
def test_default_for_multiple_dotted_source(self):
428+
class Serializer(serializers.Serializer):
429+
c = serializers.CharField(default='x', source='a.b.c')
430+
431+
assert Serializer({}).data == {'c': 'x'}
432+
assert Serializer({'a': {}}).data == {'c': 'x'}
433+
assert Serializer({'a': None}).data == {'c': 'x'}
434+
assert Serializer({'a': {'b': {}}}).data == {'c': 'x'}
435+
assert Serializer({'a': {'b': None}}).data == {'c': 'x'}
436+
437+
assert Serializer({'a': {'b': {'c': 'abc'}}}).data == {'c': 'abc'}
438+
439+
def test_default_for_nested_serializer(self):
440+
class NestedSerializer(serializers.Serializer):
441+
a = serializers.CharField(default='1')
442+
c = serializers.CharField(default='2', source='b.c')
443+
444+
class Serializer(serializers.Serializer):
445+
nested = NestedSerializer()
446+
447+
assert Serializer({'nested': None}).data == {'nested': None}
448+
assert Serializer({'nested': {}}).data == {'nested': {'a': '1', 'c': '2'}}
449+
assert Serializer({'nested': {'a': '3', 'b': {}}}).data == {'nested': {'a': '3', 'c': '2'}}
450+
assert Serializer({'nested': {'a': '3', 'b': {'c': '4'}}}).data == {'nested': {'a': '3', 'c': '4'}}
451+
427452

428453
class TestCacheSerializerData:
429454
def test_cache_serializer_data(self):

0 commit comments

Comments
 (0)