mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Move sequential creation logic to a mixin
This commit is contained in:
parent
b5f9fe6c0f
commit
a132da84c7
@ -1,9 +1,7 @@
|
|||||||
from django.db import transaction
|
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from drf_spectacular.types import OpenApiTypes
|
from drf_spectacular.types import OpenApiTypes
|
||||||
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
||||||
from rest_framework import status
|
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.renderers import JSONRenderer
|
from rest_framework.renderers import JSONRenderer
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
@ -23,6 +21,7 @@ from netbox.api.metadata import ContentTypeMetadata
|
|||||||
from netbox.api.pagination import StripCountAnnotationsPaginator
|
from netbox.api.pagination import StripCountAnnotationsPaginator
|
||||||
from netbox.api.renderers import TextRenderer
|
from netbox.api.renderers import TextRenderer
|
||||||
from netbox.api.viewsets import NetBoxModelViewSet
|
from netbox.api.viewsets import NetBoxModelViewSet
|
||||||
|
from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
|
||||||
from netbox.constants import NESTED_SERIALIZER_PREFIX
|
from netbox.constants import NESTED_SERIALIZER_PREFIX
|
||||||
from utilities.api import get_serializer_for_model
|
from utilities.api import get_serializer_for_model
|
||||||
from utilities.utils import count_related
|
from utilities.utils import count_related
|
||||||
@ -387,7 +386,12 @@ class PlatformViewSet(NetBoxModelViewSet):
|
|||||||
# Devices/modules
|
# Devices/modules
|
||||||
#
|
#
|
||||||
|
|
||||||
class DeviceViewSet(ConfigContextQuerySetMixin, ConfigTemplateRenderMixin, NetBoxModelViewSet):
|
class DeviceViewSet(
|
||||||
|
SequentialBulkCreatesMixin,
|
||||||
|
ConfigContextQuerySetMixin,
|
||||||
|
ConfigTemplateRenderMixin,
|
||||||
|
NetBoxModelViewSet
|
||||||
|
):
|
||||||
queryset = Device.objects.prefetch_related(
|
queryset = Device.objects.prefetch_related(
|
||||||
'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'site', 'location', 'rack', 'parent_bay',
|
'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'site', 'location', 'rack', 'parent_bay',
|
||||||
'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'config_template', 'tags',
|
'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'config_template', 'tags',
|
||||||
@ -415,25 +419,6 @@ class DeviceViewSet(ConfigContextQuerySetMixin, ConfigTemplateRenderMixin, NetBo
|
|||||||
|
|
||||||
return serializers.DeviceWithConfigContextSerializer
|
return serializers.DeviceWithConfigContextSerializer
|
||||||
|
|
||||||
@transaction.atomic
|
|
||||||
def create(self, request, *args, **kwargs):
|
|
||||||
# do validate / create for each item in serial instead of validating all data at once
|
|
||||||
if is_bulk := isinstance(request.data, list):
|
|
||||||
return_data = []
|
|
||||||
data_list = request.data if is_bulk else [request.data, ]
|
|
||||||
|
|
||||||
for data in data_list:
|
|
||||||
serializer = self.get_serializer(data=data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
self.perform_create(serializer)
|
|
||||||
headers = self.get_success_headers(serializer.data)
|
|
||||||
if is_bulk:
|
|
||||||
return_data.append(serializer.data)
|
|
||||||
else:
|
|
||||||
return_data = serializer.data
|
|
||||||
|
|
||||||
return Response(return_data, status=status.HTTP_201_CREATED, headers=headers)
|
|
||||||
|
|
||||||
@action(detail=True, methods=['post'], url_path='render-config', renderer_classes=[JSONRenderer, TextRenderer])
|
@action(detail=True, methods=['post'], url_path='render-config', renderer_classes=[JSONRenderer, TextRenderer])
|
||||||
def render_config(self, request, pk):
|
def render_config(self, request, pk):
|
||||||
"""
|
"""
|
||||||
|
@ -15,11 +15,12 @@ from utilities.api import get_serializer_for_model
|
|||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'BriefModeMixin',
|
'BriefModeMixin',
|
||||||
|
'BulkDestroyModelMixin',
|
||||||
'BulkUpdateModelMixin',
|
'BulkUpdateModelMixin',
|
||||||
'CustomFieldsMixin',
|
'CustomFieldsMixin',
|
||||||
'ExportTemplatesMixin',
|
'ExportTemplatesMixin',
|
||||||
'BulkDestroyModelMixin',
|
|
||||||
'ObjectValidationMixin',
|
'ObjectValidationMixin',
|
||||||
|
'SequentialBulkCreatesMixin',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -94,6 +95,30 @@ class ExportTemplatesMixin:
|
|||||||
return super().list(request, *args, **kwargs)
|
return super().list(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class SequentialBulkCreatesMixin:
|
||||||
|
"""
|
||||||
|
Perform bulk creation of new objects sequentially, rather than all at once. This ensures that any validation
|
||||||
|
which depends on the evaluation of existing objects (such as checking for free space within a rack) functions
|
||||||
|
appropriately.
|
||||||
|
"""
|
||||||
|
@transaction.atomic
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
if not isinstance(request.data, list):
|
||||||
|
# Creating a single object
|
||||||
|
return super().create(request, *args, **kwargs)
|
||||||
|
|
||||||
|
return_data = []
|
||||||
|
for data in request.data:
|
||||||
|
serializer = self.get_serializer(data=data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
self.perform_create(serializer)
|
||||||
|
return_data.append(serializer.data)
|
||||||
|
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
|
||||||
|
return Response(return_data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
class BulkUpdateModelMixin:
|
class BulkUpdateModelMixin:
|
||||||
"""
|
"""
|
||||||
Support bulk modification of objects using the list endpoint for a model. Accepts a PATCH action with a list of one
|
Support bulk modification of objects using the list endpoint for a model. Accepts a PATCH action with a list of one
|
||||||
|
Loading…
Reference in New Issue
Block a user