使用 Django Rest Framework 进行批量、部分更新

Oli*_*Oli 10 django django-rest-framework

我想一次部分更新多个项目。我已经添加了一个 mixin 来允许我批量创建(并且效果很好),但即使我添加了一个部分参数,它也不允许修补列表。

我猜这是一个路由问题。我需要一个新的视图来处理 PATCH /(而不是/id/),但我远远超出了我的深度。

对此的现有答案不适用于 3.8,或者至少对我不起作用。我需要对以下内容做什么?

class ResourceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Resource
        fields = ('id', 'name', ...)
        read_only_fields = ('id',)

 class BulkMixin:
     def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True
            kwargs['partial'] = True

        return super().get_serializer(*args, **kwargs)

class ResourceViewSet(BulkMixin, viewsets.ModelViewSet):
    serializer_class = ResourceSerializer
Run Code Online (Sandbox Code Playgroud)

Oli*_*Oli 8

在将我的头撞在这堵墙上大约 10 个小时之后,我决定正确的方法可以退居次要位置,而我会采用可行的 hack 方法。我将以下 gnarlfest 添加到我的视图中。

from rest_framework.decorators import action

@action(methods=['patch'], detail=False)
def bulk_update(self, request):

    data = {  # we need to separate out the id from the data
        i['id']: {k: v for k, v in i.items() if k != 'id'}
        for i in request.data
    }

    for inst in self.get_queryset().filter(id__in=data.keys()):
        serializer = self.get_serializer(inst, data=data[inst.id], partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()

    return Response({})
Run Code Online (Sandbox Code Playgroud)

如果我在此列表中打补丁,[{id: 123, otherfield: "abc"}, ...]现在将进行批量部分更新。我相当确定这是在执行 n+1 查询,并且它在原始 ORM 中的效率要高得多……但就目前而言,它比 n requests好得多。此外,如果 ID 不在查询集中,它会通过而不是出错。这对我有用,但对其他人可能不适用。

我会在 48 小时内悬赏这个问题,以吸引一些好的答案。