mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Implement support for bulk deletion of objects via a single REST API request
This commit is contained in:
@ -8,13 +8,13 @@ from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDo
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import ManyToManyField, ProtectedError
|
from django.db.models import ManyToManyField, ProtectedError
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from rest_framework import serializers
|
from rest_framework import mixins, serializers, status
|
||||||
from rest_framework.exceptions import APIException, ValidationError
|
from rest_framework.exceptions import APIException, ValidationError
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
|
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
from rest_framework.viewsets import ModelViewSet as _ModelViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
from .utils import dict_to_filter_params, dynamic_import
|
from .utils import dict_to_filter_params, dynamic_import
|
||||||
|
|
||||||
@ -291,11 +291,53 @@ class WritableNestedSerializer(serializers.ModelSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BulkDeleteSerializer(serializers.Serializer):
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mixins
|
||||||
|
#
|
||||||
|
|
||||||
|
class BulkDestroyModelMixin:
|
||||||
|
"""
|
||||||
|
Support bulk deletion of objects using the list endpoint for a model. Accepts a DELETE action with a list of one
|
||||||
|
or more JSON objects, each specifying the numeric ID of an object to be deleted. For example:
|
||||||
|
|
||||||
|
DELETE /api/dcim/sites/
|
||||||
|
[
|
||||||
|
{"id": 123},
|
||||||
|
{"id": 456}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
def bulk_destroy(self, request):
|
||||||
|
serializer = BulkDeleteSerializer(data=request.data, many=True)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
pk_list = [o['id'] for o in serializer.data]
|
||||||
|
qs = self.get_queryset().filter(pk__in=pk_list)
|
||||||
|
|
||||||
|
self.perform_bulk_destroy(qs)
|
||||||
|
|
||||||
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
def perform_bulk_destroy(self, objects):
|
||||||
|
with transaction.atomic():
|
||||||
|
for obj in objects:
|
||||||
|
self.perform_destroy(obj)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Viewsets
|
# Viewsets
|
||||||
#
|
#
|
||||||
|
|
||||||
class ModelViewSet(_ModelViewSet):
|
class ModelViewSet(mixins.CreateModelMixin,
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
|
mixins.UpdateModelMixin,
|
||||||
|
mixins.DestroyModelMixin,
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
BulkDestroyModelMixin,
|
||||||
|
GenericViewSet):
|
||||||
"""
|
"""
|
||||||
Accept either a single object or a list of objects to create.
|
Accept either a single object or a list of objects to create.
|
||||||
"""
|
"""
|
||||||
@ -408,6 +450,14 @@ class ModelViewSet(_ModelViewSet):
|
|||||||
|
|
||||||
class OrderedDefaultRouter(DefaultRouter):
|
class OrderedDefaultRouter(DefaultRouter):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Extend the list view mappings to support the DELETE operation
|
||||||
|
self.routes[0].mapping.update({
|
||||||
|
'delete': 'bulk_destroy',
|
||||||
|
})
|
||||||
|
|
||||||
def get_api_root_view(self, api_urls=None):
|
def get_api_root_view(self, api_urls=None):
|
||||||
"""
|
"""
|
||||||
Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
|
Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
|
||||||
|
Reference in New Issue
Block a user