mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-22 13:22:24 -06:00
Consolidate create() and update() logic into PortSerializer base class
This commit is contained in:
@@ -2,10 +2,12 @@ from drf_spectacular.types import OpenApiTypes
|
|||||||
from drf_spectacular.utils import extend_schema_field
|
from drf_spectacular.utils import extend_schema_field
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from dcim.models import FrontPort, FrontPortTemplate, PortMapping, PortTemplateMapping, RearPort, RearPortTemplate
|
||||||
from utilities.api import get_serializer_for_model
|
from utilities.api import get_serializer_for_model
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ConnectedEndpointsSerializer',
|
'ConnectedEndpointsSerializer',
|
||||||
|
'PortSerializer',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -35,3 +37,53 @@ class ConnectedEndpointsSerializer(serializers.ModelSerializer):
|
|||||||
@extend_schema_field(serializers.BooleanField)
|
@extend_schema_field(serializers.BooleanField)
|
||||||
def get_connected_endpoints_reachable(self, obj):
|
def get_connected_endpoints_reachable(self, obj):
|
||||||
return obj._path and obj._path.is_complete and obj._path.is_active
|
return obj._path and obj._path.is_complete and obj._path.is_active
|
||||||
|
|
||||||
|
|
||||||
|
class PortSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
Base serializer for front & rear port and port templates.
|
||||||
|
"""
|
||||||
|
@property
|
||||||
|
def _mapper(self):
|
||||||
|
"""
|
||||||
|
Return the model and ForeignKey field name used to track port mappings for this model.
|
||||||
|
"""
|
||||||
|
if self.Meta.model is FrontPort:
|
||||||
|
return PortMapping, 'front_port'
|
||||||
|
if self.Meta.model is RearPort:
|
||||||
|
return PortMapping, 'rear_port'
|
||||||
|
if self.Meta.model is FrontPortTemplate:
|
||||||
|
return PortTemplateMapping, 'front_port'
|
||||||
|
if self.Meta.model is RearPortTemplate:
|
||||||
|
return PortTemplateMapping, 'rear_port'
|
||||||
|
raise ValueError(f"Could not determine mapping details for {self.__class__}")
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
mappings = validated_data.pop('mappings', [])
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
|
||||||
|
# Create port mappings
|
||||||
|
mapping_model, fk_name = self._mapper
|
||||||
|
for attrs in mappings:
|
||||||
|
mapping_model.objects.create(**{
|
||||||
|
fk_name: instance,
|
||||||
|
**attrs,
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
mappings = validated_data.pop('mappings', None)
|
||||||
|
instance = super().update(instance, validated_data)
|
||||||
|
|
||||||
|
if mappings is not None:
|
||||||
|
# Update port mappings
|
||||||
|
mapping_model, fk_name = self._mapper
|
||||||
|
mapping_model.objects.filter(**{fk_name: instance}).delete()
|
||||||
|
for attrs in mappings:
|
||||||
|
mapping_model.objects.create(**{
|
||||||
|
fk_name: instance,
|
||||||
|
**attrs,
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from wireless.api.serializers_.nested import NestedWirelessLinkSerializer
|
|||||||
from wireless.api.serializers_.wirelesslans import WirelessLANSerializer
|
from wireless.api.serializers_.wirelesslans import WirelessLANSerializer
|
||||||
from wireless.choices import *
|
from wireless.choices import *
|
||||||
from wireless.models import WirelessLAN
|
from wireless.models import WirelessLAN
|
||||||
from .base import ConnectedEndpointsSerializer
|
from .base import ConnectedEndpointsSerializer, PortSerializer
|
||||||
from .cables import CabledObjectSerializer
|
from .cables import CabledObjectSerializer
|
||||||
from .devices import DeviceSerializer, MACAddressSerializer, ModuleSerializer, VirtualDeviceContextSerializer
|
from .devices import DeviceSerializer, MACAddressSerializer, ModuleSerializer, VirtualDeviceContextSerializer
|
||||||
from .manufacturers import ManufacturerSerializer
|
from .manufacturers import ManufacturerSerializer
|
||||||
@@ -307,7 +307,7 @@ class RearPortMappingSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('position', 'front_port', 'front_port_position')
|
fields = ('position', 'front_port', 'front_port_position')
|
||||||
|
|
||||||
|
|
||||||
class RearPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
|
class RearPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, PortSerializer):
|
||||||
device = DeviceSerializer(nested=True)
|
device = DeviceSerializer(nested=True)
|
||||||
module = ModuleSerializer(
|
module = ModuleSerializer(
|
||||||
nested=True,
|
nested=True,
|
||||||
@@ -331,28 +331,6 @@ class RearPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
|
|||||||
]
|
]
|
||||||
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', 'cable', '_occupied')
|
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', 'cable', '_occupied')
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', [])
|
|
||||||
instance = super().create(validated_data)
|
|
||||||
|
|
||||||
# Create FrontPort mappings
|
|
||||||
for attrs in mappings:
|
|
||||||
PortMapping.objects.create(rear_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', None)
|
|
||||||
instance = super().update(instance, validated_data)
|
|
||||||
|
|
||||||
if mappings is not None:
|
|
||||||
# Update FrontPort mappings
|
|
||||||
PortMapping.objects.filter(rear_port=instance).delete()
|
|
||||||
for attrs in mappings:
|
|
||||||
PortMapping.objects.create(rear_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
class FrontPortMappingSerializer(serializers.ModelSerializer):
|
class FrontPortMappingSerializer(serializers.ModelSerializer):
|
||||||
position = serializers.IntegerField(
|
position = serializers.IntegerField(
|
||||||
@@ -367,7 +345,7 @@ class FrontPortMappingSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('position', 'rear_port', 'rear_port_position')
|
fields = ('position', 'rear_port', 'rear_port_position')
|
||||||
|
|
||||||
|
|
||||||
class FrontPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
|
class FrontPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, PortSerializer):
|
||||||
device = DeviceSerializer(nested=True)
|
device = DeviceSerializer(nested=True)
|
||||||
module = ModuleSerializer(
|
module = ModuleSerializer(
|
||||||
nested=True,
|
nested=True,
|
||||||
@@ -391,28 +369,6 @@ class FrontPortSerializer(NetBoxModelSerializer, CabledObjectSerializer):
|
|||||||
]
|
]
|
||||||
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', 'cable', '_occupied')
|
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', 'cable', '_occupied')
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', [])
|
|
||||||
instance = super().create(validated_data)
|
|
||||||
|
|
||||||
# Create RearPort mappings
|
|
||||||
for attrs in mappings:
|
|
||||||
PortMapping.objects.create(front_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', None)
|
|
||||||
instance = super().update(instance, validated_data)
|
|
||||||
|
|
||||||
if mappings is not None:
|
|
||||||
# Update RearPort mappings
|
|
||||||
PortMapping.objects.filter(front_port=instance).delete()
|
|
||||||
for attrs in mappings:
|
|
||||||
PortMapping.objects.create(front_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleBaySerializer(NetBoxModelSerializer):
|
class ModuleBaySerializer(NetBoxModelSerializer):
|
||||||
device = DeviceSerializer(nested=True)
|
device = DeviceSerializer(nested=True)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from netbox.api.fields import ChoiceField, ContentTypeField
|
|||||||
from netbox.api.gfk_fields import GFKSerializerField
|
from netbox.api.gfk_fields import GFKSerializerField
|
||||||
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
|
||||||
from wireless.choices import *
|
from wireless.choices import *
|
||||||
|
from .base import PortSerializer
|
||||||
from .devicetypes import DeviceTypeSerializer, ModuleTypeSerializer
|
from .devicetypes import DeviceTypeSerializer, ModuleTypeSerializer
|
||||||
from .manufacturers import ManufacturerSerializer
|
from .manufacturers import ManufacturerSerializer
|
||||||
from .nested import NestedInterfaceTemplateSerializer
|
from .nested import NestedInterfaceTemplateSerializer
|
||||||
@@ -219,7 +220,7 @@ class RearPortTemplateMappingSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('position', 'front_port', 'front_port_position')
|
fields = ('position', 'front_port', 'front_port_position')
|
||||||
|
|
||||||
|
|
||||||
class RearPortTemplateSerializer(ComponentTemplateSerializer):
|
class RearPortTemplateSerializer(ComponentTemplateSerializer, PortSerializer):
|
||||||
device_type = DeviceTypeSerializer(
|
device_type = DeviceTypeSerializer(
|
||||||
required=False,
|
required=False,
|
||||||
nested=True,
|
nested=True,
|
||||||
@@ -247,28 +248,6 @@ class RearPortTemplateSerializer(ComponentTemplateSerializer):
|
|||||||
]
|
]
|
||||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', [])
|
|
||||||
instance = super().create(validated_data)
|
|
||||||
|
|
||||||
# Create FrontPort mappings
|
|
||||||
for attrs in mappings:
|
|
||||||
PortTemplateMapping.objects.create(rear_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', None)
|
|
||||||
instance = super().update(instance, validated_data)
|
|
||||||
|
|
||||||
if mappings is not None:
|
|
||||||
# Update FrontPort mappings
|
|
||||||
PortTemplateMapping.objects.filter(rear_port=instance).delete()
|
|
||||||
for attrs in mappings:
|
|
||||||
PortTemplateMapping.objects.create(rear_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateMappingSerializer(serializers.ModelSerializer):
|
class FrontPortTemplateMappingSerializer(serializers.ModelSerializer):
|
||||||
position = serializers.IntegerField(
|
position = serializers.IntegerField(
|
||||||
@@ -283,7 +262,7 @@ class FrontPortTemplateMappingSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('position', 'rear_port', 'rear_port_position')
|
fields = ('position', 'rear_port', 'rear_port_position')
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateSerializer(ComponentTemplateSerializer):
|
class FrontPortTemplateSerializer(ComponentTemplateSerializer, PortSerializer):
|
||||||
device_type = DeviceTypeSerializer(
|
device_type = DeviceTypeSerializer(
|
||||||
nested=True,
|
nested=True,
|
||||||
required=False,
|
required=False,
|
||||||
@@ -311,28 +290,6 @@ class FrontPortTemplateSerializer(ComponentTemplateSerializer):
|
|||||||
]
|
]
|
||||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', [])
|
|
||||||
instance = super().create(validated_data)
|
|
||||||
|
|
||||||
# Create RearPort mappings
|
|
||||||
for attrs in mappings:
|
|
||||||
PortTemplateMapping.objects.create(front_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
mappings = validated_data.pop('mappings', None)
|
|
||||||
instance = super().update(instance, validated_data)
|
|
||||||
|
|
||||||
if mappings is not None:
|
|
||||||
# Update RearPort assignments
|
|
||||||
PortTemplateMapping.objects.filter(front_port=instance).delete()
|
|
||||||
for attrs in mappings:
|
|
||||||
PortTemplateMapping.objects.create(front_port=instance, **attrs)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleBayTemplateSerializer(ComponentTemplateSerializer):
|
class ModuleBayTemplateSerializer(ComponentTemplateSerializer):
|
||||||
device_type = DeviceTypeSerializer(
|
device_type = DeviceTypeSerializer(
|
||||||
|
|||||||
Reference in New Issue
Block a user