Skip to content

Commit 397a89c

Browse files
committed
Add example using source=‘*’ to custom field docs.
Closes #2032 closes #3066
1 parent ea0b3b3 commit 397a89c

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

docs/api-guide/fields.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ Note that the `WritableField` class that was present in version 2.x no longer ex
561561

562562
## Examples
563563

564+
### A Basic Custom Field
565+
564566
Let's look at an example of serializing a class that represents an RGB color value:
565567

566568
class Color(object):
@@ -600,7 +602,7 @@ As an example, let's create a field that can be used to represent the class name
600602
"""
601603
return obj.__class__.__name__
602604

603-
#### Raising validation errors
605+
### Raising validation errors
604606

605607
Our `ColorField` class above currently does not perform any data validation.
606608
To indicate invalid data, we should raise a `serializers.ValidationError`, like so:
@@ -646,6 +648,75 @@ The `.fail()` method is a shortcut for raising `ValidationError` that takes a me
646648

647649
This style keeps your error messages cleaner and more separated from your code, and should be preferred.
648650

651+
### Using `source='*'`
652+
653+
Here we'll take an example of a _flat_ `DataPoint` model with `x_coordinate` and `y_coordinate` attributes.
654+
655+
class DataPoint(models.Model):
656+
label = models.CharField(max_length=50)
657+
x_coordinate = models.SmallIntegerField()
658+
y_coordinate = models.SmallIntegerField()
659+
660+
Using a custom field and `source='*'` we can provide a nested representation of
661+
the coordinate pair:
662+
663+
class CoordinateField(serializers.Field):
664+
665+
def to_representation(self, obj):
666+
ret = {
667+
"x": obj.x_coordinate,
668+
"y": obj.y_coordinate
669+
}
670+
return ret
671+
672+
def to_internal_value(self, data):
673+
ret = {
674+
"x_coordinate": data["x"],
675+
"y_coordinate": data["y"],
676+
}
677+
return ret
678+
679+
680+
class DataPointSerializer(serializers.ModelSerializer):
681+
coordinates = CoordinateField(source='*')
682+
683+
class Meta:
684+
model = DataPoint
685+
fields = ['label', 'coordinates']
686+
687+
Note that this example doesn't handle validation. Partly for that reason, in a
688+
real project, the coordinate nesting might be better handled with a nested serialiser using two
689+
`IntegerField` instances, each with `source='*'`.
690+
691+
The key points from the example, though, are:
692+
693+
* `to_representation` is passed the entire `DataPoint` object must map from that
694+
to the desired output.
695+
696+
>>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2)
697+
>>> out_serializer = DataPointSerializer(instance)
698+
>>> out_serializer.data
699+
ReturnDict([('label', 'testing'), ('coordinates', {'x': 1, 'y': 2})])
700+
701+
* Unless our field is to be read-only, `to_internal_value` must map back to a dict
702+
suitable for updating our target object. With `source='*'`, the return from
703+
`to_internal_value` will update the root validated data dictionary, rather than a single key.
704+
705+
>>> data = {
706+
... "label": "Second Example",
707+
... "coordinates": {
708+
... "x": 3,
709+
... "y": 4,
710+
... }
711+
... }
712+
>>> in_serializer = DataPointSerializer(data=data)
713+
>>> in_serializer.is_valid()
714+
True
715+
>>> in_serializer.validated_data
716+
OrderedDict([('label', 'Second Example'),
717+
('y_coordinate', 4),
718+
('x_coordinate', 3)])
719+
649720
# Third party packages
650721

651722
The following third party packages are also available.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy