content: from django.contrib.contenttypes.models import ContentType
  from drf_spectacular.types import OpenApiTypes
  from drf_spectacular.utils import extend_schema_field
  from rest_framework import serializers
  
  from dcim.choices import *
  from dcim.constants import *
  from dcim.models import Cable, CablePath, CableTermination
  from netbox.api.fields import ChoiceField, ContentTypeField
  from netbox.api.serializers import BaseModelSerializer, GenericObjectSerializer, NetBoxModelSerializer
  from tenancy.api.serializers_.tenants import TenantSerializer
  from utilities.api import get_serializer_for_model
  
  __all__ = (
      'CablePathSerializer',
      'CableSerializer',
      'CableTerminationSerializer',
      'CabledObjectSerializer',
      'TracedCableSerializer',
  )
  
  
  class CableSerializer(NetBoxModelSerializer):
      a_terminations = GenericObjectSerializer(many=True, required=False)
      b_terminations = GenericObjectSerializer(many=True, required=False)
      status = ChoiceField(choices=LinkStatusChoices, required=False)
      tenant = TenantSerializer(nested=True, required=False, allow_null=True)
      length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False, allow_null=True)
  
      class Meta:
          model = Cable
          fields = [
              'id', 'url', 'display_url', 'display', 'type', 'a_terminations', 'b_terminations', 'status', 'tenant',
              'label', 'color', 'length', 'length_unit', 'description', 'comments', 'tags', 'custom_fields', 'created',
              'last_updated',
          ]
          brief_fields = ('id', 'url', 'display', 'label', 'description')
  
  
  class TracedCableSerializer(BaseModelSerializer):
      """
      Used only while tracing a cable path.
      """
  
      class Meta:
          model = Cable
          fields = [
              'id', 'url', 'display_url', 'type', 'status', 'label', 'color', 'length', 'length_unit', 'description',
          ]
  
  
  class CableTerminationSerializer(NetBoxModelSerializer):
      termination_type = ContentTypeField(
          queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
      )
      termination = serializers.SerializerMethodField(read_only=True)
  
      class Meta:
          model = CableTermination
          fields = [
              'id', 'url', 'display', 'cable', 'cable_end', 'termination_type', 'termination_id',
              'termination', 'created', 'last_updated',
          ]
  
      @extend_schema_field(serializers.JSONField(allow_null=True))
      def get_termination(self, obj):
          serializer = get_serializer_for_model(obj.termination)
          context = {'request': self.context['request']}
          return serializer(obj.termination, nested=True, context=context).data
  
  
  class CablePathSerializer(serializers.ModelSerializer):
      path = serializers.SerializerMethodField(read_only=True)
  
      class Meta:
          model = CablePath
          fields = ['id', 'path', 'is_active', 'is_complete', 'is_split']
  
      @extend_schema_field(serializers.ListField)
      def get_path(self, obj):
          ret = []
          for nodes in obj.path_objects:
              serializer = get_serializer_for_model(nodes[0])
              context = {'request': self.context['request']}
              ret.append(serializer(nodes, nested=True, many=True, context=context).data)
          return ret
  
  
  class CabledObjectSerializer(serializers.ModelSerializer):
      cable = CableSerializer(nested=True, read_only=True, allow_null=True)
      cable_end = serializers.CharField(read_only=True)
      link_peers_type = serializers.SerializerMethodField(read_only=True, allow_null=True)
      link_peers = serializers.SerializerMethodField(read_only=True)
      _occupied = serializers.SerializerMethodField(read_only=True)
  
      @extend_schema_field(OpenApiTypes.STR)
      def get_link_peers_type(self, obj):
          """
          Return the type of the peer link terminations, or None.
          """
          if not obj.cable:
              return None
  
          if obj.link_peers:
              return f'{obj.link_peers[0]._meta.app_label}.{obj.link_peers[0]._meta.model_name}'
  
          return None
  
      @extend_schema_field(serializers.ListField)
      def get_link_peers(self, obj):
          """
          Return the appropriate serializer for the link termination model.
          """
          if not obj.link_peers:
              return []
  
          # Return serialized peer termination objects
          serializer = get_serializer_for_model(obj.link_peers[0])
          context = {'request': self.context['request']}
          return serializer(obj.link_peers, nested=True, many=True, context=context).data
  
      @extend_schema_field(serializers.BooleanField)
      def get__occupied(self, obj):
          return obj._occupied
  