djangopython-3.xdjango-rest-frameworkdjango-viewsdjango-serializer

Override to_representation in List serializer class


I have a serializer that implements the BaseSerializer class in which I'm using the to_representation function to do a function call like so:

class ItemSerializer(serializers.BaseSerializer):
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret['log'] = SERVICE.log(instance.id)
        return ret

    class Meta:
        list_serializer_class = ItemListSerializer
        model = models.Item
        fields = '__all__'

I also have a list serializer for the same ItemListSerializer which looks like this:

class ItemListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        items = [models.Item(**item) for item in validated_data]
        return models.Item.objects.bulk_create(items)

What I want to do is override the to_representation method in the ItemSerializer for when I want to get the entire list of Items. I basically want to avoid doing a function call per item and instead do a bulk call for all the items when the list of items is requested for performance reasons.

Is there a good way to do this? I followed these docs for creating the ItemListSerializer:https://www.django-rest-framework.org/api-guide/serializers/#customizing-listserializer-behavior but it only talks about overriding create and update methods.


Solution

  • You can access all items in ListSerializer.to_representation

    It should be a good place to do what you want.

    The method looks like this:

    def to_representation(self, data):
        """
        List of object instances -> List of dicts of primitive datatypes.
        """
        # Dealing with nested relationships, data can be a Manager,
        # so, first get a queryset from the Manager if needed
        iterable = data.all() if isinstance(data, models.Manager) else data
    
        return [
            self.child.to_representation(item) for item in iterable
        ]
    

    But to be honest I don't see what would you gain from it. Your use case looks like it will be no measurable performance boost.