问题
I want to partially-update multiple items at once. I've already added a mixin for allowing me to bulk-create (and that works well) but even though I've added a partial argument, it doesn't allow for patching a list.
I'm guessing that this is a routing issue. I need a new view to handle PATCH on /
(rather than /id/
), but I'm well out of my depth.
Existing answers for this don't work for 3.8, or at least haven't worked for me. What do I need to do to the following?
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
回答1:
After ~10 hours banging my head against this wall, I decided that the right way could take a back seat and I'd make do with the hack way that works. I added the following gnarlfest to my viewset.
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({})
If I patch in a list of [{id: 123, otherfield: "abc"}, ...]
this will now bulk-partial update. I'm fairly sure this is doing n+1 queries and that it'd be a lot more efficient in raw ORM... but for now, it's infinitely better than n requests. Also, if the ID isn't in the queryset, it will pass over rather than erroring. That works for me, but may not for others.
I'll stick a bounty on this question in 48h to tempt in some good answers.
回答2:
I would suggest not trying to implement this yourself. Consider using django-rest-framework-bulk. It supports bulk, partial updates and provides serializers, views, and a router to make things really simple to setup.
来源:https://stackoverflow.com/questions/53130126/bulk-partial-updates-with-django-rest-framework