Просмотр исходного кода

Initialize dynamically-resolved serializers with nested=True

Jeremy Stretch 2 лет назад
Родитель
Сommit
78e284c14f

+ 2 - 3
netbox/dcim/api/serializers_/base.py

@@ -2,7 +2,6 @@ from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 
 __all__ = (
@@ -29,9 +28,9 @@ class ConnectedEndpointsSerializer(serializers.ModelSerializer):
         Return the appropriate serializer for the type of connected object.
         """
         if endpoints := obj.connected_endpoints:
-            serializer = get_serializer_for_model(endpoints[0], prefix=NESTED_SERIALIZER_PREFIX)
+            serializer = get_serializer_for_model(endpoints[0])
             context = {'request': self.context['request']}
-            return serializer(endpoints, many=True, context=context).data
+            return serializer(endpoints, nested=True, many=True, context=context).data
 
     @extend_schema_field(serializers.BooleanField)
     def get_connected_endpoints_reachable(self, obj):

+ 6 - 7
netbox/dcim/api/serializers_/cables.py

@@ -8,7 +8,6 @@ from dcim.constants import *
 from dcim.models import Cable, CablePath, CableTermination
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import GenericObjectSerializer, NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.api.serializers_.tenants import TenantSerializer
 from utilities.api import get_serializer_for_model
 
@@ -67,9 +66,9 @@ class CableTerminationSerializer(NetBoxModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_termination(self, obj):
-        serializer = get_serializer_for_model(obj.termination, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.termination)
         context = {'request': self.context['request']}
-        return serializer(obj.termination, context=context).data
+        return serializer(obj.termination, nested=True, context=context).data
 
 
 class CablePathSerializer(serializers.ModelSerializer):
@@ -83,9 +82,9 @@ class CablePathSerializer(serializers.ModelSerializer):
     def get_path(self, obj):
         ret = []
         for nodes in obj.path_objects:
-            serializer = get_serializer_for_model(nodes[0], prefix=NESTED_SERIALIZER_PREFIX)
+            serializer = get_serializer_for_model(nodes[0])
             context = {'request': self.context['request']}
-            ret.append(serializer(nodes, context=context, many=True).data)
+            ret.append(serializer(nodes, nested=True, many=True, context=context).data)
         return ret
 
 
@@ -118,9 +117,9 @@ class CabledObjectSerializer(serializers.ModelSerializer):
             return []
 
         # Return serialized peer termination objects
-        serializer = get_serializer_for_model(obj.link_peers[0], prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.link_peers[0])
         context = {'request': self.context['request']}
-        return serializer(obj.link_peers, context=context, many=True).data
+        return serializer(obj.link_peers, nested=True, many=True, context=context).data
 
     @extend_schema_field(serializers.BooleanField)
     def get__occupied(self, obj):

+ 3 - 4
netbox/dcim/api/serializers_/device_components.py

@@ -13,10 +13,10 @@ from ipam.api.serializers_.vrfs import VRFSerializer
 from ipam.models import VLAN
 from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
 from wireless.api.nested_serializers import NestedWirelessLinkSerializer
+from wireless.api.serializers_.wirelesslans import WirelessLANSerializer
 from wireless.choices import *
 from wireless.models import WirelessLAN
 from .base import ConnectedEndpointsSerializer
@@ -24,7 +24,6 @@ from .cables import CabledObjectSerializer
 from .devices import DeviceSerializer, ModuleSerializer, VirtualDeviceContextSerializer
 from .manufacturers import ManufacturerSerializer
 from .roles import InventoryItemRoleSerializer
-from wireless.api.serializers_.wirelesslans import WirelessLANSerializer
 from ..nested_serializers import *
 
 __all__ = (
@@ -364,6 +363,6 @@ class InventoryItemSerializer(NetBoxModelSerializer):
     def get_component(self, obj):
         if obj.component is None:
             return None
-        serializer = get_serializer_for_model(obj.component, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.component)
         context = {'request': self.context['request']}
-        return serializer(obj.component, context=context).data
+        return serializer(obj.component, nested=True, context=context).data

+ 2 - 3
netbox/dcim/api/serializers_/devicetype_components.py

@@ -10,7 +10,6 @@ from dcim.models import (
 )
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import ValidatedModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from wireless.choices import *
 from .devicetypes import DeviceTypeSerializer, ModuleTypeSerializer
@@ -323,6 +322,6 @@ class InventoryItemTemplateSerializer(ValidatedModelSerializer):
     def get_component(self, obj):
         if obj.component is None:
             return None
-        serializer = get_serializer_for_model(obj.component, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.component)
         context = {'request': self.context['request']}
-        return serializer(obj.component, context=context).data
+        return serializer(obj.component, nested=True, context=context).data

+ 4 - 7
netbox/dcim/api/views.py

@@ -7,7 +7,6 @@ from rest_framework.response import Response
 from rest_framework.routers import APIRootView
 from rest_framework.viewsets import ViewSet
 
-from circuits.models import Circuit
 from dcim import filtersets
 from dcim.constants import CABLE_TRACE_SVG_DEFAULT_WIDTH
 from dcim.models import *
@@ -18,10 +17,8 @@ from netbox.api.metadata import ContentTypeMetadata
 from netbox.api.pagination import StripCountAnnotationsPaginator
 from netbox.api.viewsets import NetBoxModelViewSet, MPTTLockedMixin
 from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from utilities.query_functions import CollateAsChar
-from utilities.utils import count_related
 from . import serializers
 from .exceptions import MissingFilterException
 
@@ -60,16 +57,16 @@ class PathEndpointMixin(object):
         # Serialize path objects, iterating over each three-tuple in the path
         for near_ends, cable, far_ends in obj.trace():
             if near_ends:
-                serializer_a = get_serializer_for_model(near_ends[0], prefix=NESTED_SERIALIZER_PREFIX)
-                near_ends = serializer_a(near_ends, many=True, context={'request': request}).data
+                serializer_a = get_serializer_for_model(near_ends[0])
+                near_ends = serializer_a(near_ends, nested=True, many=True, context={'request': request}).data
             else:
                 # Path is split; stop here
                 break
             if cable:
                 cable = serializers.TracedCableSerializer(cable[0], context={'request': request}).data
             if far_ends:
-                serializer_b = get_serializer_for_model(far_ends[0], prefix=NESTED_SERIALIZER_PREFIX)
-                far_ends = serializer_b(far_ends, many=True, context={'request': request}).data
+                serializer_b = get_serializer_for_model(far_ends[0])
+                far_ends = serializer_b(far_ends, nested=True, many=True, context={'request': request}).data
 
             path.append((near_ends, cable, far_ends))
 

+ 7 - 11
netbox/extras/api/customfields.py

@@ -1,13 +1,12 @@
 from django.contrib.contenttypes.models import ContentType
 from django.utils.translation import gettext as _
-from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.types import OpenApiTypes
+from drf_spectacular.utils import extend_schema_field
 from rest_framework.fields import Field
 from rest_framework.serializers import ValidationError
 
 from extras.choices import CustomFieldTypeChoices
 from extras.models import CustomField
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 
 
@@ -58,11 +57,11 @@ class CustomFieldsDataField(Field):
         for cf in self._get_custom_fields():
             value = cf.deserialize(obj.get(cf.name))
             if value is not None and cf.type == CustomFieldTypeChoices.TYPE_OBJECT:
-                serializer = get_serializer_for_model(cf.object_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
-                value = serializer(value, context=self.parent.context).data
+                serializer = get_serializer_for_model(cf.object_type.model_class())
+                value = serializer(value, nested=True, context=self.parent.context).data
             elif value is not None and cf.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT:
-                serializer = get_serializer_for_model(cf.object_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
-                value = serializer(value, many=True, context=self.parent.context).data
+                serializer = get_serializer_for_model(cf.object_type.model_class())
+                value = serializer(value, nested=True, many=True, context=self.parent.context).data
             data[cf.name] = value
 
         return data
@@ -80,12 +79,9 @@ class CustomFieldsDataField(Field):
                     CustomFieldTypeChoices.TYPE_OBJECT,
                     CustomFieldTypeChoices.TYPE_MULTIOBJECT
             ):
-                serializer_class = get_serializer_for_model(
-                    model=cf.object_type.model_class(),
-                    prefix=NESTED_SERIALIZER_PREFIX
-                )
+                serializer_class = get_serializer_for_model(cf.object_type.model_class())
                 many = cf.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT
-                serializer = serializer_class(data=data[cf.name], many=many, context=self.parent.context)
+                serializer = serializer_class(data=data[cf.name], nested=True, many=many, context=self.parent.context)
                 if serializer.is_valid():
                     data[cf.name] = [obj['id'] for obj in serializer.data] if many else serializer.data['id']
                 else:

+ 3 - 3
netbox/extras/api/serializers_/attachments.py

@@ -6,7 +6,6 @@ from core.models import ContentType
 from extras.models import ImageAttachment
 from netbox.api.fields import ContentTypeField
 from netbox.api.serializers import ValidatedModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 
 __all__ = (
@@ -46,5 +45,6 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_parent(self, obj):
-        serializer = get_serializer_for_model(obj.parent, prefix=NESTED_SERIALIZER_PREFIX)
-        return serializer(obj.parent, context={'request': self.context['request']}).data
+        serializer = get_serializer_for_model(obj.parent)
+        context = {'request': self.context['request']}
+        return serializer(obj.parent, nested=True, context=context).data

+ 3 - 3
netbox/extras/api/serializers_/bookmarks.py

@@ -5,7 +5,6 @@ from core.models import ContentType
 from extras.models import Bookmark
 from netbox.api.fields import ContentTypeField
 from netbox.api.serializers import ValidatedModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from users.api.serializers_.users import UserSerializer
 from utilities.api import get_serializer_for_model
 
@@ -31,5 +30,6 @@ class BookmarkSerializer(ValidatedModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_object(self, instance):
-        serializer = get_serializer_for_model(instance.object, prefix=NESTED_SERIALIZER_PREFIX)
-        return serializer(instance.object, context={'request': self.context['request']}).data
+        serializer = get_serializer_for_model(instance.object)
+        context = {'request': self.context['request']}
+        return serializer(instance.object, nested=True, context=context).data

+ 2 - 6
netbox/extras/api/serializers_/change_logging.py

@@ -6,7 +6,6 @@ from extras.models import ObjectChange
 from netbox.api.exceptions import SerializerNotFound
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import BaseModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from users.api.serializers_.users import UserSerializer
 from utilities.api import get_serializer_for_model
 
@@ -48,12 +47,9 @@ class ObjectChangeSerializer(BaseModelSerializer):
             return None
 
         try:
-            serializer = get_serializer_for_model(obj.changed_object, prefix=NESTED_SERIALIZER_PREFIX)
+            serializer = get_serializer_for_model(obj.changed_object)
         except SerializerNotFound:
             return obj.object_repr
-        context = {
-            'request': self.context['request']
-        }
-        data = serializer(obj.changed_object, context=context).data
+        data = serializer(obj.changed_object, nested=True, context={'request': self.context['request']}).data
 
         return data

+ 2 - 6
netbox/extras/api/serializers_/events.py

@@ -7,7 +7,6 @@ from extras.choices import *
 from extras.models import EventRule, Webhook
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from .scripts import ScriptSerializer
 
@@ -51,11 +50,8 @@ class EventRuleSerializer(NetBoxModelSerializer):
             instance = script.python_class() if script.python_class else None
             return ScriptSerializer(instance, nested=True, context=context).data
         else:
-            serializer = get_serializer_for_model(
-                model=instance.action_object_type.model_class(),
-                prefix=NESTED_SERIALIZER_PREFIX
-            )
-            return serializer(instance.action_object, context=context).data
+            serializer = get_serializer_for_model(instance.action_object_type.model_class())
+            return serializer(instance.action_object, nested=True, context=context).data
 
 
 #

+ 2 - 6
netbox/extras/api/serializers_/journaling.py

@@ -8,7 +8,6 @@ from extras.choices import *
 from extras.models import JournalEntry
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 
 __all__ = (
@@ -59,9 +58,6 @@ class JournalEntrySerializer(NetBoxModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_assigned_object(self, instance):
-        serializer = get_serializer_for_model(
-            instance.assigned_object_type.model_class(),
-            prefix=NESTED_SERIALIZER_PREFIX
-        )
+        serializer = get_serializer_for_model(instance.assigned_object_type.model_class())
         context = {'request': self.context['request']}
-        return serializer(instance.assigned_object, context=context).data
+        return serializer(instance.assigned_object, nested=True, context=context).data

+ 2 - 3
netbox/ipam/api/serializers_/fhrpgroups.py

@@ -5,7 +5,6 @@ from rest_framework import serializers
 from ipam.models import FHRPGroup, FHRPGroupAssignment
 from netbox.api.fields import ContentTypeField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from .ip import IPAddressSerializer
 
@@ -48,6 +47,6 @@ class FHRPGroupAssignmentSerializer(NetBoxModelSerializer):
     def get_interface(self, obj):
         if obj.interface is None:
             return None
-        serializer = get_serializer_for_model(obj.interface, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.interface)
         context = {'request': self.context['request']}
-        return serializer(obj.interface, context=context).data
+        return serializer(obj.interface, nested=True, context=context).data

+ 5 - 7
netbox/ipam/api/serializers_/ip.py

@@ -8,16 +8,14 @@ from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
 from ipam.models import Aggregate, IPAddress, IPRange, Prefix
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.api.serializers_.tenants import TenantSerializer
 from utilities.api import get_serializer_for_model
-from ..field_serializers import IPAddressField, IPNetworkField
-from ..nested_serializers import *
-
 from .asns import RIRSerializer
-from .vrfs import VRFSerializer
 from .roles import RoleSerializer
 from .vlans import VLANSerializer
+from .vrfs import VRFSerializer
+from ..field_serializers import IPAddressField, IPNetworkField
+from ..nested_serializers import *
 
 __all__ = (
     'AggregateSerializer',
@@ -174,9 +172,9 @@ class IPAddressSerializer(NetBoxModelSerializer):
     def get_assigned_object(self, obj):
         if obj.assigned_object is None:
             return None
-        serializer = get_serializer_for_model(obj.assigned_object, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.assigned_object)
         context = {'request': self.context['request']}
-        return serializer(obj.assigned_object, context=context).data
+        return serializer(obj.assigned_object, nested=True, context=context).data
 
 
 class AvailableIPSerializer(serializers.Serializer):

+ 2 - 5
netbox/ipam/api/serializers_/vlans.py

@@ -8,11 +8,9 @@ from ipam.constants import VLANGROUP_SCOPE_TYPES
 from ipam.models import VLAN, VLANGroup
 from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.api.serializers_.tenants import TenantSerializer
 from utilities.api import get_serializer_for_model
 from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
-
 from .roles import RoleSerializer
 
 __all__ = (
@@ -53,10 +51,9 @@ class VLANGroupSerializer(NetBoxModelSerializer):
     def get_scope(self, obj):
         if obj.scope_id is None:
             return None
-        serializer = get_serializer_for_model(obj.scope, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.scope)
         context = {'request': self.context['request']}
-
-        return serializer(obj.scope, context=context).data
+        return serializer(obj.scope, nested=True, context=context).data
 
 
 class VLANSerializer(NetBoxModelSerializer):

+ 2 - 4
netbox/netbox/api/serializers/generic.py

@@ -3,7 +3,6 @@ from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 
 from netbox.api.fields import ContentTypeField
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from utilities.api import get_serializer_for_model
 from utilities.utils import content_type_identifier
 
@@ -40,6 +39,5 @@ class GenericObjectSerializer(serializers.Serializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_object(self, obj):
-        serializer = get_serializer_for_model(obj, prefix=NESTED_SERIALIZER_PREFIX)
-        # context = {'request': self.context['request']}
-        return serializer(obj, context=self.context).data
+        serializer = get_serializer_for_model(obj)
+        return serializer(obj, nested=True, context=self.context).data

+ 1 - 0
netbox/netbox/constants.py

@@ -1,4 +1,5 @@
 # Prefix for nested serializers
+# TODO: Remove in v4.1
 NESTED_SERIALIZER_PREFIX = 'Nested'
 
 # RQ queue names

+ 2 - 3
netbox/tenancy/api/serializers_/contacts.py

@@ -5,7 +5,6 @@ from rest_framework import serializers
 
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.choices import ContactPriorityChoices
 from tenancy.models import ContactAssignment, Contact, ContactGroup, ContactRole
 from utilities.api import get_serializer_for_model
@@ -77,6 +76,6 @@ class ContactAssignmentSerializer(NetBoxModelSerializer):
 
     @extend_schema_field(OpenApiTypes.OBJECT)
     def get_object(self, instance):
-        serializer = get_serializer_for_model(instance.content_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(instance.content_type.model_class())
         context = {'request': self.context['request']}
-        return serializer(instance.object, context=context).data
+        return serializer(instance.object, nested=True, context=context).data

+ 2 - 3
netbox/vpn/api/serializers_/l2vpn.py

@@ -6,7 +6,6 @@ from ipam.api.serializers_.vrfs import RouteTargetSerializer
 from ipam.models import RouteTarget
 from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.api.serializers_.tenants import TenantSerializer
 from utilities.api import get_serializer_for_model
 from vpn.choices import *
@@ -66,6 +65,6 @@ class L2VPNTerminationSerializer(NetBoxModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_assigned_object(self, instance):
-        serializer = get_serializer_for_model(instance.assigned_object, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(instance.assigned_object)
         context = {'request': self.context['request']}
-        return serializer(instance.assigned_object, context=context).data
+        return serializer(instance.assigned_object, nested=True, context=context).data

+ 2 - 4
netbox/vpn/api/serializers_/tunnels.py

@@ -5,12 +5,10 @@ from rest_framework import serializers
 from ipam.api.serializers_.ip import IPAddressSerializer
 from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
 from netbox.api.serializers import NetBoxModelSerializer
-from netbox.constants import NESTED_SERIALIZER_PREFIX
 from tenancy.api.serializers_.tenants import TenantSerializer
 from utilities.api import get_serializer_for_model
 from vpn.choices import *
 from vpn.models import Tunnel, TunnelGroup, TunnelTermination
-
 from .crypto import IPSecProfileSerializer
 
 __all__ = (
@@ -109,6 +107,6 @@ class TunnelTerminationSerializer(NetBoxModelSerializer):
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_termination(self, obj):
-        serializer = get_serializer_for_model(obj.termination, prefix=NESTED_SERIALIZER_PREFIX)
+        serializer = get_serializer_for_model(obj.termination)
         context = {'request': self.context['request']}
-        return serializer(obj.termination, context=context).data
+        return serializer(obj.termination, nested=True, context=context).data