Django Rest框架序列化程序返回应在更新时过滤掉的嵌套记录

Django Rest框架序列化程序返回应在更新时过滤掉的嵌套记录,django,django-rest-framework,Django,Django Rest Framework,我重写了FormSerializer的更新方法。如有必要,它会将某些嵌套字段记录标记为不推荐使用。但是,Api调用返回所有记录,即使我的get\u queryset过滤掉了所有不推荐使用的记录。据我所知,正在调用get_queryset来获取实例,然后将实例传递给序列化程序。此实例不包含任何以前不推荐使用的记录 update方法完成后,似乎必须运行另一个查询来获取所有这些嵌套记录并序列化它们。这仅在更新时发生。调用self.perform\u update()时,序列化程序保存在UpdateMo

我重写了FormSerializer的更新方法。如有必要,它会将某些嵌套字段记录标记为不推荐使用。但是,Api调用返回所有记录,即使我的get\u queryset过滤掉了所有不推荐使用的记录。据我所知,正在调用get_queryset来获取实例,然后将实例传递给序列化程序。此实例不包含任何以前不推荐使用的记录

update方法完成后,似乎必须运行另一个查询来获取所有这些嵌套记录并序列化它们。这仅在更新时发生。调用self.perform\u update()时,序列化程序保存在UpdateModelMixin.update()中时可能会发生这种情况

我在标准get请求中获得了正确的记录。知道第二个查询在哪里被调用以及如何覆盖它吗?或者,我应该能够在to_表示中编辑序列化数据,但这将是低效的,我想首先了解这里发生了什么

看法

序列化程序

class FormSerializer(serializers.ModelSerializer):
  id = serializers.IntegerField(required=False, allow_null=True)
  fields = FieldSerializer(many=True)

  class Meta:
      model = Form
      fields = '__all__'

  @staticmethod
  def eager_loading(queryset):
      return queryset.prefetch_related(Prefetch('fields',queryset=Field.objects.filter(is_deprecated=False).order_by('field_order')))

我认为,这个答案应该是一个评论,但没有足够的声誉

在序列化程序的
update
方法之前调用的
get\u queryset
方法

我的意思是:

  • 调用
    更新
    ->供查看
  • 查看调用
    get\u queryset
    ->现在我们还没有更新
    是否已弃用
  • 视图找到要更新的对象,并调用序列化程序的
    update
    ->进行更改
  • 视图从序列化程序的
    update
    方法返回实例
  • 因此,您的
    字段
    字段与第2点相同。预取不是这样工作的吗?我是说装一次,就这样


    因此,您需要设法更新预取的
    字段。

    如果查看modelviewset的更新方法,您会发现它会使与
    预取相关的
    数据无效,因此您的快速加载无法工作

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
    
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
    
        return Response(serializer.data)
    

    这样做是因为预取的数据在更新后可能会过时。因此,您可以覆盖更新方法并在更新后重新执行预取

    您可以共享您的更新方法吗?如果它是私有的,你能告诉我更新方法的返回变量是什么吗?只是澄清一下,GET请求返回的结果是正确的,而PUT请求则不是?你只是发送了一个对象的PUT,对吗?如果是PUT,则对象应始终为returned@kamilyrb我的update变量返回instance@Programmingjoe这是正确的。我的get请求返回在急切加载方法中描述的过滤结果。但是PUT返回所有相关记录,就好像从未应用过过滤器一样。我已经验证了我在update方法中返回的实例是否具有正确过滤的记录。@Alex我有点困惑,因为PUT请求应该只返回已更新的记录,而您是说它返回的是记录列表?令人困惑的是预取字段被正确过滤。问题是API最终会重新计算所有相关字段记录。即使是设置为的记录,在以前的调用中也会被弃用,并且不在我的初始预取中。在某个时候,它必须进行二次调用以获取我不想要的所有其他记录。这正是发生的情况。谢谢你的解释!
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
    
        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
    
        return Response(serializer.data)