From 5677fab2f9b7da6981acc64beb2ad099e9e1f414 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 22 Sep 2020 11:55:46 -0400 Subject: [PATCH] Support bulk operations for both PUT and PATCH --- netbox/netbox/api.py | 5 ++++- netbox/utilities/api.py | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/netbox/netbox/api.py b/netbox/netbox/api.py index 05885f2e8..4b60084c6 100644 --- a/netbox/netbox/api.py +++ b/netbox/netbox/api.py @@ -12,7 +12,10 @@ from users.models import Token def is_custom_action(action): 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', } diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index 977b37119..e652656d7 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -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.is_valid(raise_exception=True) qs = self.get_queryset().filter( @@ -329,18 +330,22 @@ class BulkUpdateModelMixin: 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) - def perform_bulk_update(self, objects, update_data): + def perform_bulk_update(self, objects, update_data, partial): with transaction.atomic(): for obj in objects: 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) self.perform_update(serializer) + def bulk_partial_update(self, request, *args, **kwargs): + kwargs['partial'] = True + return self.bulk_update(request, *args, **kwargs) + class BulkDestroyModelMixin: """ @@ -353,7 +358,7 @@ class BulkDestroyModelMixin: {"id": 456} ] """ - def bulk_destroy(self, request): + def bulk_destroy(self, request, *args, **kwargs): serializer = BulkOperationSerializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) qs = self.get_queryset().filter( @@ -499,7 +504,8 @@ class OrderedDefaultRouter(DefaultRouter): # Extend the list view mappings to support the DELETE operation self.routes[0].mapping.update({ - 'patch': 'bulk_update', + 'put': 'bulk_update', + 'patch': 'bulk_partial_update', 'delete': 'bulk_destroy', })