Field to_representation function seems to have inconsistent arguments

383 views
Skip to first unread message

rus...@vida.com

unread,
Jul 7, 2021, 1:54:51 PM7/7/21
to Django REST framework
Hi all,

I'm troubleshooting a bug in the drf-spectacular library that we're trying to use to generate Open Api 3.0 schemas from our DRF codebase (link: https://github.com/tfranzel/drf-spectacular/issues/422), and I stumbled across what looks like a bit of an inconsistency in what arguments are expected to be passed to the to_representation function on different field types.

Inside of Serializer.to_representation, I see the following code, where it first calls field.get_attribute, and then calls the to_representation function on each field individually (link https://github.com/encode/django-rest-framework/blob/98e56e0327596db352b35fa3b3dc8355dc9bd030/rest_framework/serializers.py#L493).

for field in fields:
try:
attribute = field.get_attribute(instance)
except SkipField:
continue

# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
ret[field.field_name] = field.to_representation(attribute)

What is interesting, is that different fields return different types from the call to field.get_attribute.  Most fields seem to fetch the attribute from the instance that is passed in and return the attribute.  Some fields however, like ModelField and SerializerMethodField, just return the instance, without fetching an attribute.

This means that the to_representation functions for ModelField and SerializerMethodField expect the entire instance to be passed in as the argument, whereas most fields expect just the attribute.

Is this different signature for Field.to_representation expected?  And are there any suggestions for how to handle it, perhaps there is a way to know which fields have different signatures?  

We're trying to use to_representation to make sure that we're using primitive types when generating the Open API schemas.

Thanks for the help,
Russell

Carl Nobile

unread,
Jul 7, 2021, 4:40:50 PM7/7/21
to django-res...@googlegroups.com
If I'm not mistaken there are two types of incoming data an object or a dict, but the output type should always be a dictionary.
The `field.get_attribute` method is used to get values from embedded fields on the serializer.
I override the `to_representation` method all the time because I write custom serializers often.
So it's not only fields that have the `to_representation`, but as I mentioned above serializers have them also, but both cases should always return an ordered dict.
I agree that this can be confusing but the problem is that it's not always known which one will be called and how deep the calls will go.
~Carl

--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-rest-framework/02af1ce6-3269-46d2-82b9-272a3c81cadcn%40googlegroups.com.


--
-------------------------------------------------------------------------------
Carl J. Nobile (Software Engineer)
carl....@gmail.com
-------------------------------------------------------------------------------
Reply all
Reply to author
Forward
0 new messages