预取相关数据(prefetch_related)在Django REST框架序列化器中的SerializerMethodField不起作用。

10

我有一个包含嵌套序列化器字段的序列化器。我已经设置好了急切加载,一切都很顺利。

然而,我不得不向嵌套字段添加一些自定义过滤器,这需要使用 SerializerMethodField。

在这个更改之后,预取相关的急切加载不再起作用了。我该如何优化带有 SerializerMethodField 的序列化器?

以下是我的初始工作设置:

# 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

这是我的修改后的序列化程序,但它并不能正常工作:

# 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

请添加 NotWorkingSerializer 的精确代码。 - Sardorbek Imomaliev
@SardorbekImomaliev 即使我删除筛选,它仍然无法工作。 - roob
可能是Django使用manager related时出现的重复查询问题的重复内容。 - Alexandr Tatarinov
1
因为你正在执行 instance.related_field_name.objects.all()。如果它是一个相关字段,那么这样做非常奇怪,应该使用 instance.related_field_name.all() - Sardorbek Imomaliev
@SardorbekImomaliev 是的,抱歉那是一个打字错误。 - roob
@AlexandrTatarinov 那个问题确实有帮助。我认为因为我需要进行一个过滤器调用,该调用将模型的实例作为参数,所以在这里没有预取优化可以做。我想我会通过在我的视图中覆盖“list”来稍后处理过滤。 - roob
1个回答

3

不要在序列化器中执行prefetch请求,而是可以在视图中实际的查询集(queryset)中进行。您可以使用自定义查询覆盖get_queryset方法。不确定您的实际查询是什么,但是可以举个例子,您可以这样做:

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

这个查询集已经包含了您的相关字段。您无需在序列化器中编写自定义逻辑。


当他需要过滤嵌套的序列化器时,那样做是行不通的。 - Thorvald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接