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

Add dynamic nesting support to SerializedPKRelatedField

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

+ 3 - 2
netbox/circuits/api/serializers_/providers.py

@@ -1,7 +1,7 @@
 from rest_framework import serializers
 
 from circuits.models import Provider, ProviderAccount, ProviderNetwork
-from ipam.api.nested_serializers import NestedASNSerializer
+from ipam.api.serializers_.asns import ASNSerializer
 from ipam.models import ASN
 from netbox.api.fields import RelatedObjectCountField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer
@@ -24,7 +24,8 @@ class ProviderSerializer(NetBoxModelSerializer):
     )
     asns = SerializedPKRelatedField(
         queryset=ASN.objects.all(),
-        serializer=NestedASNSerializer,
+        serializer=ASNSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 9 - 6
netbox/dcim/api/serializers_/device_components.py

@@ -10,21 +10,21 @@ from dcim.models import (
 )
 from ipam.api.serializers_.vlans import VLANSerializer
 from ipam.api.serializers_.vrfs import VRFSerializer
-from ipam.api.nested_serializers import NestedVLANSerializer
 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 NestedWirelessLANSerializer, NestedWirelessLinkSerializer
+from wireless.api.nested_serializers import NestedWirelessLinkSerializer
 from wireless.choices import *
 from wireless.models import WirelessLAN
 from .base import ConnectedEndpointsSerializer
 from .cables import CabledObjectSerializer
-from .devices import DeviceSerializer, ModuleSerializer
+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__ = (
@@ -173,7 +173,8 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
     device = DeviceSerializer(nested=True)
     vdcs = SerializedPKRelatedField(
         queryset=VirtualDeviceContext.objects.all(),
-        serializer=NestedVirtualDeviceContextSerializer,
+        serializer=VirtualDeviceContextSerializer,
+        nested=True,
         required=False,
         many=True
     )
@@ -196,7 +197,8 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
     untagged_vlan = VLANSerializer(nested=True, required=False, allow_null=True)
     tagged_vlans = SerializedPKRelatedField(
         queryset=VLAN.objects.all(),
-        serializer=NestedVLANSerializer,
+        serializer=VLANSerializer,
+        nested=True,
         required=False,
         many=True
     )
@@ -205,7 +207,8 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
     wireless_link = NestedWirelessLinkSerializer(read_only=True, allow_null=True)
     wireless_lans = SerializedPKRelatedField(
         queryset=WirelessLAN.objects.all(),
-        serializer=NestedWirelessLANSerializer,
+        serializer=WirelessLANSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 1 - 1
netbox/dcim/api/serializers_/devices.py

@@ -6,7 +6,7 @@ from rest_framework import serializers
 
 from dcim.choices import *
 from dcim.models import Device, DeviceBay, Module, VirtualDeviceContext
-from extras.api.serializers_.provisioning import ConfigTemplateSerializer
+from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
 from ipam.api.serializers_.ip import IPAddressSerializer
 from netbox.api.fields import ChoiceField, RelatedObjectCountField
 from netbox.api.serializers import NetBoxModelSerializer

+ 1 - 1
netbox/dcim/api/serializers_/platforms.py

@@ -1,7 +1,7 @@
 from rest_framework import serializers
 
 from dcim.models import Platform
-from extras.api.serializers_.provisioning import ConfigTemplateSerializer
+from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
 from netbox.api.fields import RelatedObjectCountField
 from netbox.api.serializers import NetBoxModelSerializer
 from .manufacturers import ManufacturerSerializer

+ 1 - 1
netbox/dcim/api/serializers_/roles.py

@@ -1,7 +1,7 @@
 from rest_framework import serializers
 
 from dcim.models import DeviceRole, InventoryItemRole
-from extras.api.serializers_.provisioning import ConfigTemplateSerializer
+from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
 from netbox.api.fields import RelatedObjectCountField
 from netbox.api.serializers import NetBoxModelSerializer
 

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

@@ -3,7 +3,7 @@ from timezone_field.rest_framework import TimeZoneSerializerField
 
 from dcim.choices import *
 from dcim.models import Location, Region, Site, SiteGroup
-from ipam.api.nested_serializers import NestedASNSerializer
+from ipam.api.serializers_.asns import ASNSerializer
 from ipam.models import ASN
 from netbox.api.fields import ChoiceField, RelatedObjectCountField, SerializedPKRelatedField
 from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
@@ -55,7 +55,8 @@ class SiteSerializer(NetBoxModelSerializer):
     time_zone = TimeZoneSerializerField(required=False, allow_null=True)
     asns = SerializedPKRelatedField(
         queryset=ASN.objects.all(),
-        serializer=NestedASNSerializer,
+        serializer=ASNSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 2 - 1
netbox/extras/api/serializers.py

@@ -8,7 +8,8 @@ from .serializers_.dashboard import *
 from .serializers_.events import *
 from .serializers_.exporttemplates import *
 from .serializers_.journaling import *
-from .serializers_.provisioning import *
+from .serializers_.configcontexts import *
+from .serializers_.configtemplates import *
 from .serializers_.savedfilters import *
 from .serializers_.scripts import *
 from .serializers_.tags import *

+ 31 - 47
netbox/extras/api/serializers_/provisioning.py → netbox/extras/api/serializers_/configcontexts.py

@@ -1,25 +1,21 @@
 from rest_framework import serializers
 
 from core.api.serializers_.data import DataFileSerializer, DataSourceSerializer
-from dcim.api.nested_serializers import (
-    NestedDeviceRoleSerializer, NestedDeviceTypeSerializer, NestedLocationSerializer, NestedPlatformSerializer,
-    NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer,
-)
+from dcim.api.serializers_.devicetypes import DeviceTypeSerializer
+from dcim.api.serializers_.platforms import PlatformSerializer
+from dcim.api.serializers_.roles import DeviceRoleSerializer
+from dcim.api.serializers_.sites import LocationSerializer, RegionSerializer, SiteSerializer, SiteGroupSerializer
 from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
-from extras.models import ConfigContext, ConfigTemplate, Tag
+from extras.models import ConfigContext, Tag
 from netbox.api.fields import SerializedPKRelatedField
 from netbox.api.serializers import ValidatedModelSerializer
-from netbox.api.serializers.features import TaggableModelSerializer
-from tenancy.api.nested_serializers import NestedTenantSerializer, NestedTenantGroupSerializer
+from tenancy.api.serializers_.tenants import TenantSerializer, TenantGroupSerializer
 from tenancy.models import Tenant, TenantGroup
-from virtualization.api.nested_serializers import (
-    NestedClusterGroupSerializer, NestedClusterSerializer, NestedClusterTypeSerializer,
-)
+from virtualization.api.serializers_.clusters import ClusterSerializer, ClusterGroupSerializer, ClusterTypeSerializer
 from virtualization.models import Cluster, ClusterGroup, ClusterType
 
 __all__ = (
     'ConfigContextSerializer',
-    'ConfigTemplateSerializer',
 )
 
 
@@ -27,73 +23,85 @@ class ConfigContextSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:configcontext-detail')
     regions = SerializedPKRelatedField(
         queryset=Region.objects.all(),
-        serializer=NestedRegionSerializer,
+        serializer=RegionSerializer,
+        nested=True,
         required=False,
         many=True
     )
     site_groups = SerializedPKRelatedField(
         queryset=SiteGroup.objects.all(),
-        serializer=NestedSiteGroupSerializer,
+        serializer=SiteGroupSerializer,
+        nested=True,
         required=False,
         many=True
     )
     sites = SerializedPKRelatedField(
         queryset=Site.objects.all(),
-        serializer=NestedSiteSerializer,
+        serializer=SiteSerializer,
+        nested=True,
         required=False,
         many=True
     )
     locations = SerializedPKRelatedField(
         queryset=Location.objects.all(),
-        serializer=NestedLocationSerializer,
+        serializer=LocationSerializer,
+        nested=True,
         required=False,
         many=True
     )
     device_types = SerializedPKRelatedField(
         queryset=DeviceType.objects.all(),
-        serializer=NestedDeviceTypeSerializer,
+        serializer=DeviceTypeSerializer,
+        nested=True,
         required=False,
         many=True
     )
     roles = SerializedPKRelatedField(
         queryset=DeviceRole.objects.all(),
-        serializer=NestedDeviceRoleSerializer,
+        serializer=DeviceRoleSerializer,
+        nested=True,
         required=False,
         many=True
     )
     platforms = SerializedPKRelatedField(
         queryset=Platform.objects.all(),
-        serializer=NestedPlatformSerializer,
+        serializer=PlatformSerializer,
+        nested=True,
         required=False,
         many=True
     )
     cluster_types = SerializedPKRelatedField(
         queryset=ClusterType.objects.all(),
-        serializer=NestedClusterTypeSerializer,
+        serializer=ClusterTypeSerializer,
+        nested=True,
         required=False,
         many=True
     )
     cluster_groups = SerializedPKRelatedField(
         queryset=ClusterGroup.objects.all(),
-        serializer=NestedClusterGroupSerializer,
+        serializer=ClusterGroupSerializer,
+        nested=True,
         required=False,
         many=True
     )
     clusters = SerializedPKRelatedField(
         queryset=Cluster.objects.all(),
-        serializer=NestedClusterSerializer,
+        serializer=ClusterSerializer,
+        nested=True,
         required=False,
         many=True
     )
     tenant_groups = SerializedPKRelatedField(
         queryset=TenantGroup.objects.all(),
-        serializer=NestedTenantGroupSerializer,
+        serializer=TenantGroupSerializer,
+        nested=True,
         required=False,
         many=True
     )
     tenants = SerializedPKRelatedField(
         queryset=Tenant.objects.all(),
-        serializer=NestedTenantSerializer,
+        serializer=TenantSerializer,
+        nested=True,
         required=False,
         many=True
     )
@@ -121,27 +129,3 @@ class ConfigContextSerializer(ValidatedModelSerializer):
             'created', 'last_updated',
         ]
         brief_fields = ('id', 'url', 'display', 'name', 'description')
-
-
-#
-# Config templates
-#
-
-class ConfigTemplateSerializer(TaggableModelSerializer, ValidatedModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='extras-api:configtemplate-detail')
-    data_source = DataSourceSerializer(
-        nested=True,
-        required=False
-    )
-    data_file = DataFileSerializer(
-        nested=True,
-        required=False
-    )
-
-    class Meta:
-        model = ConfigTemplate
-        fields = [
-            'id', 'url', 'display', 'name', 'description', 'environment_params', 'template_code', 'data_source',
-            'data_path', 'data_file', 'data_synced', 'tags', 'created', 'last_updated',
-        ]
-        brief_fields = ('id', 'url', 'display', 'name', 'description')

+ 30 - 0
netbox/extras/api/serializers_/configtemplates.py

@@ -0,0 +1,30 @@
+from rest_framework import serializers
+
+from core.api.serializers_.data import DataFileSerializer, DataSourceSerializer
+from extras.models import ConfigTemplate
+from netbox.api.serializers import ValidatedModelSerializer
+from netbox.api.serializers.features import TaggableModelSerializer
+
+__all__ = (
+    'ConfigTemplateSerializer',
+)
+
+
+class ConfigTemplateSerializer(TaggableModelSerializer, ValidatedModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='extras-api:configtemplate-detail')
+    data_source = DataSourceSerializer(
+        nested=True,
+        required=False
+    )
+    data_file = DataFileSerializer(
+        nested=True,
+        required=False
+    )
+
+    class Meta:
+        model = ConfigTemplate
+        fields = [
+            'id', 'url', 'display', 'name', 'description', 'environment_params', 'template_code', 'data_source',
+            'data_path', 'data_file', 'data_synced', 'tags', 'created', 'last_updated',
+        ]
+        brief_fields = ('id', 'url', 'display', 'name', 'description')

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

@@ -9,7 +9,7 @@ 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 ..nested_serializers import *
+from .scripts import ScriptSerializer
 
 __all__ = (
     'EventRuleSerializer',
@@ -49,7 +49,7 @@ class EventRuleSerializer(NetBoxModelSerializer):
         if instance.action_type == EventRuleActionChoices.SCRIPT:
             script = instance.action_object
             instance = script.python_class() if script.python_class else None
-            return NestedScriptSerializer(instance, context=context).data
+            return ScriptSerializer(instance, nested=True, context=context).data
         else:
             serializer = get_serializer_for_model(
                 model=instance.action_object_type.model_class(),

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

@@ -7,7 +7,7 @@ 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 ..nested_serializers import *
+from .ip import IPAddressSerializer
 
 __all__ = (
     'FHRPGroupAssignmentSerializer',
@@ -17,7 +17,7 @@ __all__ = (
 
 class FHRPGroupSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='ipam-api:fhrpgroup-detail')
-    ip_addresses = NestedIPAddressSerializer(many=True, read_only=True)
+    ip_addresses = IPAddressSerializer(nested=True, many=True, read_only=True)
 
     class Meta:
         model = FHRPGroup

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

@@ -6,7 +6,7 @@ from ipam.models import IPAddress, Service, ServiceTemplate
 from netbox.api.fields import ChoiceField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer
 from virtualization.api.serializers_.virtualmachines import VirtualMachineSerializer
-from ..nested_serializers import *
+from .ip import IPAddressSerializer
 
 __all__ = (
     'ServiceSerializer',
@@ -34,7 +34,8 @@ class ServiceSerializer(NetBoxModelSerializer):
     protocol = ChoiceField(choices=ServiceProtocolChoices, required=False)
     ipaddresses = SerializedPKRelatedField(
         queryset=IPAddress.objects.all(),
-        serializer=NestedIPAddressSerializer,
+        serializer=IPAddressSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 15 - 16
netbox/ipam/api/serializers_/vrfs.py

@@ -4,7 +4,6 @@ from ipam.models import RouteTarget, VRF
 from netbox.api.fields import RelatedObjectCountField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer
 from tenancy.api.serializers_.tenants import TenantSerializer
-from ..nested_serializers import *
 
 __all__ = (
     'RouteTargetSerializer',
@@ -12,18 +11,31 @@ __all__ = (
 )
 
 
+class RouteTargetSerializer(NetBoxModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='ipam-api:routetarget-detail')
+    tenant = TenantSerializer(nested=True, required=False, allow_null=True)
+
+    class Meta:
+        model = RouteTarget
+        fields = [
+            'id', 'url', 'display', 'name', 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created',
+            'last_updated',
+        ]
+        brief_fields = ('id', 'url', 'display', 'name', 'description')
+
+
 class VRFSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail')
     tenant = TenantSerializer(nested=True, required=False, allow_null=True)
     import_targets = SerializedPKRelatedField(
         queryset=RouteTarget.objects.all(),
-        serializer=NestedRouteTargetSerializer,
+        serializer=RouteTargetSerializer,
         required=False,
         many=True
     )
     export_targets = SerializedPKRelatedField(
         queryset=RouteTarget.objects.all(),
-        serializer=NestedRouteTargetSerializer,
+        serializer=RouteTargetSerializer,
         required=False,
         many=True
     )
@@ -40,16 +52,3 @@ class VRFSerializer(NetBoxModelSerializer):
             'prefix_count',
         ]
         brief_fields = ('id', 'url', 'display', 'name', 'rd', 'description', 'prefix_count')
-
-
-class RouteTargetSerializer(NetBoxModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='ipam-api:routetarget-detail')
-    tenant = TenantSerializer(nested=True, required=False, allow_null=True)
-
-    class Meta:
-        model = RouteTarget
-        fields = [
-            'id', 'url', 'display', 'name', 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created',
-            'last_updated',
-        ]
-        brief_fields = ('id', 'url', 'display', 'name', 'description')

+ 4 - 2
netbox/netbox/api/fields.py

@@ -132,13 +132,15 @@ class SerializedPKRelatedField(PrimaryKeyRelatedField):
     Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related
     objects in a ManyToManyField while still allowing a set of primary keys to be written.
     """
-    def __init__(self, serializer, **kwargs):
+    def __init__(self, serializer, nested=False, **kwargs):
         self.serializer = serializer
+        self.nested = nested
         self.pk_field = kwargs.pop('pk_field', None)
+
         super().__init__(**kwargs)
 
     def to_representation(self, value):
-        return self.serializer(value, context={'request': self.context['request']}).data
+        return self.serializer(value, nested=self.nested, context={'request': self.context['request']}).data
 
 
 @extend_schema_field(OpenApiTypes.INT64)

+ 5 - 3
netbox/users/api/serializers_/permissions.py

@@ -6,7 +6,7 @@ from rest_framework import serializers
 from netbox.api.fields import ContentTypeField, SerializedPKRelatedField
 from netbox.api.serializers import ValidatedModelSerializer
 from users.models import ObjectPermission
-from ..nested_serializers import *
+from .users import GroupSerializer, UserSerializer
 
 __all__ = (
     'ObjectPermissionSerializer',
@@ -21,13 +21,15 @@ class ObjectPermissionSerializer(ValidatedModelSerializer):
     )
     groups = SerializedPKRelatedField(
         queryset=Group.objects.all(),
-        serializer=NestedGroupSerializer,
+        serializer=GroupSerializer,
+        nested=True,
         required=False,
         many=True
     )
     users = SerializedPKRelatedField(
         queryset=get_user_model().objects.all(),
-        serializer=NestedUserSerializer,
+        serializer=UserSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 12 - 12
netbox/users/api/serializers_/users.py

@@ -6,7 +6,6 @@ from rest_framework import serializers
 
 from netbox.api.fields import SerializedPKRelatedField
 from netbox.api.serializers import ValidatedModelSerializer
-from ..nested_serializers import *
 
 __all__ = (
     'GroupSerializer',
@@ -14,11 +13,22 @@ __all__ = (
 )
 
 
+class GroupSerializer(ValidatedModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='users-api:group-detail')
+    user_count = serializers.IntegerField(read_only=True)
+
+    class Meta:
+        model = Group
+        fields = ('id', 'url', 'display', 'name', 'user_count')
+        brief_fields = ('id', 'url', 'display', 'name')
+
+
 class UserSerializer(ValidatedModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='users-api:user-detail')
     groups = SerializedPKRelatedField(
         queryset=Group.objects.all(),
-        serializer=NestedGroupSerializer,
+        serializer=GroupSerializer,
+        nested=True,
         required=False,
         many=True
     )
@@ -60,13 +70,3 @@ class UserSerializer(ValidatedModelSerializer):
         if full_name := obj.get_full_name():
             return f"{obj.username} ({full_name})"
         return obj.username
-
-
-class GroupSerializer(ValidatedModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='users-api:group-detail')
-    user_count = serializers.IntegerField(read_only=True)
-
-    class Meta:
-        model = Group
-        fields = ('id', 'url', 'display', 'name', 'user_count')
-        brief_fields = ('id', 'url', 'display', 'name')

+ 4 - 5
netbox/virtualization/api/serializers_/virtualmachines.py

@@ -6,8 +6,7 @@ from dcim.api.serializers_.platforms import PlatformSerializer
 from dcim.api.serializers_.roles import DeviceRoleSerializer
 from dcim.api.serializers_.sites import SiteSerializer
 from dcim.choices import InterfaceModeChoices
-from extras.api.serializers_.provisioning import ConfigTemplateSerializer
-from ipam.api.nested_serializers import NestedVLANSerializer
+from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
 from ipam.api.serializers_.ip import IPAddressSerializer
 from ipam.api.serializers_.vlans import VLANSerializer
 from ipam.api.serializers_.vrfs import VRFSerializer
@@ -18,9 +17,8 @@ from tenancy.api.serializers_.tenants import TenantSerializer
 from virtualization.choices import *
 from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
 from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
-from ..nested_serializers import *
-
 from .clusters import ClusterSerializer
+from ..nested_serializers import *
 
 __all__ = (
     'VMInterfaceSerializer',
@@ -89,7 +87,8 @@ class VMInterfaceSerializer(NetBoxModelSerializer):
     untagged_vlan = VLANSerializer(nested=True, required=False, allow_null=True)
     tagged_vlans = SerializedPKRelatedField(
         queryset=VLAN.objects.all(),
-        serializer=NestedVLANSerializer,
+        serializer=VLANSerializer,
+        nested=True,
         required=False,
         many=True
     )

+ 4 - 3
netbox/vpn/api/serializers_/crypto.py

@@ -4,7 +4,6 @@ from netbox.api.fields import ChoiceField, SerializedPKRelatedField
 from netbox.api.serializers import NetBoxModelSerializer
 from vpn.choices import *
 from vpn.models import IKEPolicy, IKEProposal, IPSecPolicy, IPSecProfile, IPSecProposal
-from ..nested_serializers import *
 
 __all__ = (
     'IKEPolicySerializer',
@@ -54,7 +53,8 @@ class IKEPolicySerializer(NetBoxModelSerializer):
     )
     proposals = SerializedPKRelatedField(
         queryset=IKEProposal.objects.all(),
-        serializer=NestedIKEProposalSerializer,
+        serializer=IKEProposalSerializer,
+        nested=True,
         required=False,
         many=True
     )
@@ -94,7 +94,8 @@ class IPSecPolicySerializer(NetBoxModelSerializer):
     )
     proposals = SerializedPKRelatedField(
         queryset=IPSecProposal.objects.all(),
-        serializer=NestedIPSecProposalSerializer,
+        serializer=IPSecProposalSerializer,
+        nested=True,
         required=False,
         many=True
     )

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

@@ -2,7 +2,7 @@ from django.contrib.contenttypes.models import ContentType
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 
-from ipam.api.nested_serializers import NestedRouteTargetSerializer
+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
@@ -23,13 +23,15 @@ class L2VPNSerializer(NetBoxModelSerializer):
     type = ChoiceField(choices=L2VPNTypeChoices, required=False)
     import_targets = SerializedPKRelatedField(
         queryset=RouteTarget.objects.all(),
-        serializer=NestedRouteTargetSerializer,
+        serializer=RouteTargetSerializer,
+        nested=True,
         required=False,
         many=True
     )
     export_targets = SerializedPKRelatedField(
         queryset=RouteTarget.objects.all(),
-        serializer=NestedRouteTargetSerializer,
+        serializer=RouteTargetSerializer,
+        nested=True,
         required=False,
         many=True
     )