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.models import ManyToManyField, ProtectedError
|
||||
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.permissions import BasePermission
|
||||
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
|
||||
from rest_framework.response import Response
|
||||
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
|
||||
|
||||
@ -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
|
||||
#
|
||||
|
||||
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.
|
||||
"""
|
||||
@ -408,6 +450,14 @@ class ModelViewSet(_ModelViewSet):
|
||||
|
||||
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):
|
||||
"""
|
||||
Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
|
||||
|
Reference in New Issue
Block a user