Pull in Serializers for Vapor overrides

* Avoids modifications with upstream methods
 * Overrides VLAN, Interface, and ConnectedEndpoint serializers for Vapor specific needs
This commit is contained in:
Marco Ceppi 2019-12-15 07:09:16 -05:00
parent 4b23149dff
commit 9fa125f1a4

View File

@ -1,24 +1,112 @@
from rest_framework import serializers from rest_framework import serializers
from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from drf_yasg.utils import swagger_serializer_method
from dcim.constants import CONNECTION_STATUS_CHOICES, IFACE_TYPE_CHOICES
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from dcim.api.nested_serializers import ( from dcim.api.nested_serializers import (
NestedDeviceSerializer, NestedDeviceSerializer,
NestedInterfaceSerializer,
NestedCableSerializer, NestedCableSerializer,
) )
from dcim.api.serializers import ( from dcim.api.serializers import (
InterfaceConnectionSerializer, InterfaceConnectionSerializer,
ConnectedEndpointSerializer,
IFACE_TYPE_CHOICES, IFACE_TYPE_CHOICES,
IFACE_MODE_CHOICES, IFACE_MODE_CHOICES,
) )
from dcim.models import Interface from dcim.models import Interface
from ipam.api.nested_serializers import NestedVLANSerializer from ipam.api.nested_serializers import NestedPrefixSerializer
from ipam.models import VLAN from ipam.models import VLAN, Prefix
from tenancy.api.nested_serializers import NestedTenantGroupSerializer from tenancy.api.nested_serializers import NestedTenantGroupSerializer
from utilities.api import ChoiceField, ValidatedModelSerializer, SerializedPKRelatedField from utilities.api import ChoiceField, ValidatedModelSerializer, SerializedPKRelatedField, WritableNestedSerializer
from tenancy.models import Tenant as Customer from tenancy.models import Tenant as Customer
from utilities.utils import dynamic_import
def get_serializer_for_model(model, prefix=''):
"""
Dynamically resolve and return the appropriate serializer for a model.
"""
app_name, model_name = model._meta.label.split('.')
serializer_name = '{}.api.serializers.{}{}Serializer'.format(
app_name, prefix, model_name
)
override_serializer_name = 'vapor.api.serializers.{}{}Serializer'.format(
prefix, model_name
)
try:
return dynamic_import(override_serializer_name)
except AttributeError:
pass
try:
return dynamic_import(serializer_name)
except AttributeError:
raise SerializerNotFound(
"Could not determine serializer for {}.{} with prefix '{}'".format(app_name, model_name, prefix)
)
class NestedVLANSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
prefixes = SerializedPKRelatedField(
queryset=Prefix.objects.all(),
serializer=NestedPrefixSerializer,
required=False,
many=True,
)
class Meta:
model = VLAN
fields = ['id', 'url', 'vid', 'name', 'display_name', 'prefixes']
class NestedInterfaceSerializer(WritableNestedSerializer):
device = NestedDeviceSerializer(read_only=True)
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
type = ChoiceField(choices=IFACE_TYPE_CHOICES, required=False)
untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
tagged_vlans = SerializedPKRelatedField(
queryset=VLAN.objects.all(),
serializer=NestedVLANSerializer,
required=False,
many=True,
)
class Meta:
model = Interface
fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status', 'type', 'untagged_vlan', 'tagged_vlans']
class ConnectedEndpointSerializer(ValidatedModelSerializer):
connected_endpoint_type = serializers.SerializerMethodField(read_only=True)
connected_endpoint = serializers.SerializerMethodField(read_only=True)
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True)
def get_connected_endpoint_type(self, obj):
if hasattr(obj, 'connected_endpoint') and obj.connected_endpoint is not None:
return '{}.{}'.format(
obj.connected_endpoint._meta.app_label,
obj.connected_endpoint._meta.model_name
)
return None
@swagger_serializer_method(serializer_or_field=serializers.DictField)
def get_connected_endpoint(self, obj):
"""
Return the appropriate serializer for the type of connected object.
"""
if getattr(obj, 'connected_endpoint', None) is None:
return None
serializer = get_serializer_for_model(obj.connected_endpoint, prefix='Nested')
context = {'request': self.context['request']}
data = serializer(obj.connected_endpoint, context=context).data
return data
class CustomerSerializer(TaggitSerializer, CustomFieldModelSerializer): class CustomerSerializer(TaggitSerializer, CustomFieldModelSerializer):