Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prefetch_related does not work for SerializerMethodField in django REST framework serializer

I have a serializer that has a nested serializer field. I had set up eager loading and everything was working great.

However, I had do add some custom filtering to the nested field, which required a SerializerMethodField.

After that change, the prefetch_related eager loading is no longer working. How can I optimize a serializer with SerializerMethodField?

Here was my initial, working setup:

# views.py
class MyView(generics.ListAPIView):
    serializer_class = WorkingSerializer

    def get_queryset(self):
        queryset = MyModel.objects.all()
        queryset = self.get_serializer_class().setup_eager_loading(queryset)
        return queryset

# serializers.py
class WorkingSerializer(serializers.ModelSerializer):
    related_field_name = CustomSerializer(many=True)

    @staticmethod
    def setup_eager_loading(queryset):
        queryset = queryset.prefetch_related('related_field_name')
        return queryset

And here is my changed serializer that doesn't work:

# serializers.py
class NotWorkingSerializer(serializers.ModelSerializer):
    related_field_name = serializers.SerializerMethodField('get_related_field')

    def get_related_field(self, instance):
        queryset = instance.related_field_name.all()
        # some filtering done here
        return queryset

    @staticmethod
    def setup_eager_loading(queryset):
        queryset = queryset.prefetch_related('related_field_name')
        return queryset
like image 240
roob Avatar asked May 17 '18 02:05

roob


1 Answers

Instead of doing the prefetch request in the serializer, you can do that in your actual queryset coming from the View. You can override get_queryset method with the custom query. Not sure what is your actual query but for an example you can do something like:

def get_queryset(self):
    queryset = Model.objects.preftech_related("related_field")
    return queryset

and this queryset will already have your related field in it. You won't have to write custom logic in the serializer.

like image 131
Atul Mishra Avatar answered Oct 31 '22 23:10

Atul Mishra