Support bulk operations for both PUT and PATCH

This commit is contained in:
Jeremy Stretch 2020-09-22 11:55:46 -04:00
parent a998c826a8
commit 5677fab2f9
2 changed files with 16 additions and 7 deletions

View File

@ -12,7 +12,10 @@ from users.models import Token
def is_custom_action(action): def is_custom_action(action):
return action not in { return action not in {
'retrieve', 'list', 'create', 'update', 'partial_update', 'destroy', 'bulk_update', 'bulk_destroy' # Default actions
'retrieve', 'list', 'create', 'update', 'partial_update', 'destroy',
# Bulk operations
'bulk_update', 'bulk_partial_update', 'bulk_destroy',
} }

View File

@ -317,7 +317,8 @@ class BulkUpdateModelMixin:
} }
] ]
""" """
def bulk_update(self, request): def bulk_update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
serializer = BulkOperationSerializer(data=request.data, many=True) serializer = BulkOperationSerializer(data=request.data, many=True)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
qs = self.get_queryset().filter( qs = self.get_queryset().filter(
@ -329,18 +330,22 @@ class BulkUpdateModelMixin:
obj.pop('id'): obj for obj in request.data obj.pop('id'): obj for obj in request.data
} }
self.perform_bulk_update(qs, update_data) self.perform_bulk_update(qs, update_data, partial=partial)
return Response(status=status.HTTP_200_OK) return Response(status=status.HTTP_200_OK)
def perform_bulk_update(self, objects, update_data): def perform_bulk_update(self, objects, update_data, partial):
with transaction.atomic(): with transaction.atomic():
for obj in objects: for obj in objects:
data = update_data.get(obj.id) data = update_data.get(obj.id)
serializer = self.get_serializer(obj, data=data, partial=True) serializer = self.get_serializer(obj, data=data, partial=partial)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
self.perform_update(serializer) self.perform_update(serializer)
def bulk_partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.bulk_update(request, *args, **kwargs)
class BulkDestroyModelMixin: class BulkDestroyModelMixin:
""" """
@ -353,7 +358,7 @@ class BulkDestroyModelMixin:
{"id": 456} {"id": 456}
] ]
""" """
def bulk_destroy(self, request): def bulk_destroy(self, request, *args, **kwargs):
serializer = BulkOperationSerializer(data=request.data, many=True) serializer = BulkOperationSerializer(data=request.data, many=True)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
qs = self.get_queryset().filter( qs = self.get_queryset().filter(
@ -499,7 +504,8 @@ class OrderedDefaultRouter(DefaultRouter):
# Extend the list view mappings to support the DELETE operation # Extend the list view mappings to support the DELETE operation
self.routes[0].mapping.update({ self.routes[0].mapping.update({
'patch': 'bulk_update', 'put': 'bulk_update',
'patch': 'bulk_partial_update',
'delete': 'bulk_destroy', 'delete': 'bulk_destroy',
}) })