Skip to content

ListSerializer awaits each item consecutively #57

@ElectronApplications

Description

@ElectronApplications

adrf/adrf/serializers.py

Lines 178 to 181 in 697ebf0

if isinstance(data, models.query.QuerySet):
return [await self.child.ato_representation(item) async for item in data]
else:
return [await self.child.ato_representation(item) for item in data]

When using the default ListSerializer, it calls ato_representation on each item and awaits them one at a time. And that kind of behavior might not be very useful when dealing with a list of async serializers.

The problem I have in my project, is that I have a serializer, which makes an HTTP request, and then I have a list of those serializers:

class ItemSerializer(AsyncSerializer):
    makes_a_request = SerializerMethodField()
    async def get_makes_a_request(self):
        return await function_that_makes_a_request()

class ItemsSerializer(AsyncSerializer):
    items = ItemSerializer(many=True)

This results in each consecutive request waiting for the previous one to complete - basically the same as if I used synchronous serializers. Here's what I use in my project, to overcome this issue:

# Put this in the list_serializer_class field in the Meta class
class ParallelListSerializer(aserializers.ListSerializer):
    async def ato_representation(self, data):
        if isinstance(data, models.Manager):
            data = data.all()

        tasks = []
        if isinstance(data, models.query.QuerySet):
            tasks = [self.child.ato_representation(item) async for item in data]
        else:
            tasks = [self.child.ato_representation(item) for item in data]
        
        return await asyncio.gather(*tasks)
    # NOTE: acreate has the same problem in ListSerializer

Wouldn't it make sense to make this the default behavior? Although, someone might actually be relying on the current order of execution, in which case you could introduce a separate serializer for this (like the one above).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions