class CableSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='dcim-api:cable-detail') termination_a_type = ContentTypeField( queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)) termination_b_type = ContentTypeField( queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)) termination_a = serializers.SerializerMethodField(read_only=True) termination_b = serializers.SerializerMethodField(read_only=True) status = ChoiceField(choices=CableStatusChoices, required=False) length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False) class Meta: model = Cable fields = [ 'id', 'url', 'display', 'termination_a_type', 'termination_a_id', 'termination_a', 'termination_b_type', 'termination_b_id', 'termination_b', 'type', 'status', 'label', 'color', 'length', 'length_unit', 'tags', 'custom_fields', ] def _get_termination(self, obj, side): """ Serialize a nested representation of a termination. """ if side.lower() not in ['a', 'b']: raise ValueError("Termination side must be either A or B.") termination = getattr(obj, 'termination_{}'.format(side.lower())) if termination is None: return None serializer = get_serializer_for_model(termination, prefix='Nested') context = {'request': self.context['request']} data = serializer(termination, context=context).data return data @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_termination_a(self, obj): return self._get_termination(obj, 'a') @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_termination_b(self, obj): return self._get_termination(obj, 'b')
class CablePathSerializer(serializers.ModelSerializer): origin_type = ContentTypeField(read_only=True) origin = serializers.SerializerMethodField(read_only=True) destination_type = ContentTypeField(read_only=True) destination = serializers.SerializerMethodField(read_only=True) path = serializers.SerializerMethodField(read_only=True) class Meta: model = CablePath fields = [ 'id', 'origin_type', 'origin', 'destination_type', 'destination', 'path', 'is_active', 'is_split', ] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_origin(self, obj): """ Return the appropriate serializer for the origin. """ serializer = get_serializer_for_model(obj.origin, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.origin, context=context).data @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_destination(self, obj): """ Return the appropriate serializer for the destination, if any. """ if obj.destination_id is not None: serializer = get_serializer_for_model(obj.destination, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.destination, context=context).data return None @swagger_serializer_method(serializer_or_field=serializers.ListField) def get_path(self, obj): ret = [] for node in obj.get_path(): serializer = get_serializer_for_model(node, prefix='Nested') context = {'request': self.context['request']} ret.append(serializer(node, context=context).data) return ret
class FHRPGroupAssignmentSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='tenancy-api:contactassignment-detail') group = NestedFHRPGroupSerializer() interface_type = ContentTypeField(queryset=ContentType.objects.all()) interface = serializers.SerializerMethodField(read_only=True) class Meta: model = FHRPGroupAssignment fields = [ 'id', 'url', 'display', 'group', 'interface_type', 'interface_id', 'interface', 'priority', 'created', 'last_updated', ] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_interface(self, obj): if obj.interface is None: return None serializer = get_serializer_for_model(obj.interface, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.interface, context=context).data
class ImageAttachmentSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:imageattachment-detail') content_type = ContentTypeField( queryset=ContentType.objects.all() ) parent = serializers.SerializerMethodField(read_only=True) class Meta: model = ImageAttachment fields = [ 'id', 'url', 'display', 'content_type', 'object_id', 'parent', 'name', 'image', 'image_height', 'image_width', 'created', 'last_updated', ] def validate(self, data): # Validate that the parent object exists try: data['content_type'].get_object_for_this_type(id=data['object_id']) except ObjectDoesNotExist: raise serializers.ValidationError( "Invalid parent object: {} ID {}".format(data['content_type'], data['object_id']) ) # Enforce model validation super().validate(data) return data @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_parent(self, obj): serializer = get_serializer_for_model(obj.parent, prefix='Nested') return serializer(obj.parent, context={'request': self.context['request']}).data
class WebhookSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:webhook-detail') content_types = ContentTypeField(queryset=ContentType.objects.filter( FeatureQuery('webhooks').get_query()), many=True) class Meta: model = Webhook fields = [ 'id', 'url', 'display', 'content_types', 'name', 'type_create', 'type_update', 'type_delete', 'payload_url', 'enabled', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret', 'ssl_verification', 'ca_file_path', ]
class IPAddressSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) vrf = NestedVRFSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) status = ChoiceField(choices=IPAddressStatusChoices, required=False) role = ChoiceField(choices=IPAddressRoleChoices, allow_blank=True, required=False) assigned_object_type = ContentTypeField( queryset=ContentType.objects.filter(IPADDRESS_ASSIGNMENT_MODELS), required=False, allow_null=True ) assigned_object = serializers.SerializerMethodField(read_only=True) nat_inside = NestedIPAddressSerializer(required=False, allow_null=True) nat_outside = NestedIPAddressSerializer(read_only=True) class Meta: model = IPAddress fields = [ 'id', 'url', 'display', 'family', 'address', 'vrf', 'tenant', 'status', 'role', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside', 'dns_name', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] read_only_fields = ['family'] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_assigned_object(self, obj): if obj.assigned_object is None: return None serializer = get_serializer_for_model(obj.assigned_object, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.assigned_object, context=context).data
class CustomFieldSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:customfield-detail') content_types = ContentTypeField(queryset=ContentType.objects.filter( FeatureQuery('custom_fields').get_query()), many=True) type = ChoiceField(choices=CustomFieldTypeChoices) filter_logic = ChoiceField(choices=CustomFieldFilterLogicChoices, required=False) class Meta: model = CustomField fields = [ 'id', 'url', 'display', 'content_types', 'type', 'name', 'label', 'description', 'required', 'filter_logic', 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', ]
class ObjectPermissionSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='users-api:objectpermission-detail') object_types = ContentTypeField(queryset=ContentType.objects.all(), many=True) groups = SerializedPKRelatedField(queryset=Group.objects.all(), serializer=NestedGroupSerializer, required=False, many=True) users = SerializedPKRelatedField(queryset=User.objects.all(), serializer=NestedUserSerializer, required=False, many=True) class Meta: model = ObjectPermission fields = ( 'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'groups', 'users', 'actions', 'constraints', )
class ImageAttachmentSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:imageattachment-detail') content_type = ContentTypeField(queryset=ContentType.objects.all()) parent = serializers.SerializerMethodField(read_only=True) class Meta: model = ImageAttachment fields = [ 'id', 'url', 'display', 'content_type', 'object_id', 'parent', 'name', 'image', 'image_height', 'image_width', 'created', ] def validate(self, data): # Validate that the parent object exists try: data['content_type'].get_object_for_this_type(id=data['object_id']) except ObjectDoesNotExist: raise serializers.ValidationError( "Invalid parent object: {} ID {}".format( data['content_type'], data['object_id'])) # Enforce model validation super().validate(data) return data @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_parent(self, obj): # Static mapping of models to their nested serializers if isinstance(obj.parent, Device): serializer = NestedDeviceSerializer elif isinstance(obj.parent, Rack): serializer = NestedRackSerializer elif isinstance(obj.parent, Site): serializer = NestedSiteSerializer else: raise Exception( "Unexpected type of parent object for ImageAttachment") return serializer(obj.parent, context={ 'request': self.context['request'] }).data
class ExportTemplateSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:exporttemplate-detail') content_type = ContentTypeField(queryset=ContentType.objects.filter( FeatureQuery('export_templates').get_query()), ) class Meta: model = ExportTemplate fields = [ 'id', 'url', 'content_type', 'name', 'description', 'template_code', 'mime_type', 'file_extension' ]
class CustomLinkSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:customlink-detail') content_type = ContentTypeField( queryset=ContentType.objects.filter(FeatureQuery('custom_links').get_query()) ) class Meta: model = CustomLink fields = [ 'id', 'url', 'display', 'content_type', 'name', 'link_text', 'link_url', 'weight', 'group_name', 'button_class', 'new_window', 'created', 'last_updated', ]
class JournalEntrySerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:journalentry-detail') assigned_object_type = ContentTypeField(queryset=ContentType.objects.all()) assigned_object = serializers.SerializerMethodField(read_only=True) created_by = serializers.PrimaryKeyRelatedField( allow_null=True, queryset=User.objects.all(), required=False, default=serializers.CurrentUserDefault()) kind = ChoiceField(choices=JournalEntryKindChoices, required=False) class Meta: model = JournalEntry fields = [ 'id', 'url', 'display', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'created', 'created_by', 'kind', 'comments', ] def validate(self, data): # Validate that the parent object exists if 'assigned_object_type' in data and 'assigned_object_id' in data: try: data['assigned_object_type'].get_object_for_this_type( id=data['assigned_object_id']) except ObjectDoesNotExist: raise serializers.ValidationError( f"Invalid assigned_object: {data['assigned_object_type']} ID {data['assigned_object_id']}" ) # Enforce model validation super().validate(data) return data @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_assigned_object(self, instance): serializer = get_serializer_for_model( instance.assigned_object_type.model_class(), prefix='Nested') context = {'request': self.context['request']} return serializer(instance.assigned_object, context=context).data
class VLANGroupSerializer(OrganizationalModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='ipam-api:vlangroup-detail') scope_type = ContentTypeField( queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), required=False) scope = serializers.SerializerMethodField(read_only=True) vlan_count = serializers.IntegerField(read_only=True) class Meta: model = VLANGroup fields = [ 'id', 'url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'description', 'custom_fields', 'created', 'last_updated', 'vlan_count', ] validators = [] def validate(self, data): # Validate uniqueness of name and slug if a site has been assigned. if data.get('site', None): for field in ['name', 'slug']: validator = UniqueTogetherValidator( queryset=VLANGroup.objects.all(), fields=('site', field)) validator(data, self) # Enforce model validation super().validate(data) return data def get_scope(self, obj): if obj.scope_id is None: return None serializer = get_serializer_for_model(obj.scope, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.scope, context=context).data
class JobResultSerializer(BaseModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:jobresult-detail') user = NestedUserSerializer( read_only=True ) status = ChoiceField(choices=JobResultStatusChoices, read_only=True) obj_type = ContentTypeField( read_only=True ) class Meta: model = JobResult fields = [ 'id', 'url', 'display', 'created', 'completed', 'name', 'obj_type', 'status', 'user', 'data', 'job_id', ]
class SecretSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='secrets-api:secret-detail') assigned_object_type = ContentTypeField( queryset=ContentType.objects.filter(SECRET_ASSIGNMENT_MODELS)) assigned_object = serializers.SerializerMethodField(read_only=True) role = NestedSecretRoleSerializer() plaintext = serializers.CharField() class Meta: model = Secret fields = [ 'id', 'url', 'display', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'role', 'name', 'plaintext', 'hash', 'tags', 'custom_fields', 'created', 'last_updated', ] validators = [] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_assigned_object(self, obj): serializer = get_serializer_for_model(obj.assigned_object, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.assigned_object, context=context).data def validate(self, data): # Encrypt plaintext data using the master key provided from the view context if data.get('plaintext'): s = Secret(plaintext=data['plaintext']) s.encrypt(self.context['master_key']) data['ciphertext'] = s.ciphertext data['hash'] = s.hash super().validate(data) return data
class ObjectChangeSerializer(BaseModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='extras-api:objectchange-detail') user = NestedUserSerializer(read_only=True) action = ChoiceField(choices=ObjectChangeActionChoices, read_only=True) changed_object_type = ContentTypeField(read_only=True) changed_object = serializers.SerializerMethodField(read_only=True) class Meta: model = ObjectChange fields = [ 'id', 'url', 'display', 'time', 'user', 'user_name', 'request_id', 'action', 'changed_object_type', 'changed_object_id', 'changed_object', 'prechange_data', 'postchange_data', ] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_changed_object(self, obj): """ Serialize a nested representation of the changed object. """ if obj.changed_object is None: return None try: serializer = get_serializer_for_model(obj.changed_object, prefix='Nested') except SerializerNotFound: return obj.object_repr context = {'request': self.context['request']} data = serializer(obj.changed_object, context=context).data return data
class NestedObjectPermissionSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField( view_name='users-api:objectpermission-detail') object_types = ContentTypeField(queryset=ContentType.objects.all(), many=True) groups = serializers.SerializerMethodField(read_only=True) users = serializers.SerializerMethodField(read_only=True) class Meta: model = ObjectPermission fields = [ 'id', 'url', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions' ] def get_groups(self, obj): return [g.name for g in obj.groups.all()] def get_users(self, obj): return [u.username for u in obj.users.all()]
class VLANGroupSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='ipam-api:vlangroup-detail') scope_type = ContentTypeField( queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), required=False, default=None) scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) scope = serializers.SerializerMethodField(read_only=True) vlan_count = serializers.IntegerField(read_only=True) class Meta: model = VLANGroup fields = [ 'id', 'url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count', ] validators = [] def get_scope(self, obj): if obj.scope_id is None: return None serializer = get_serializer_for_model(obj.scope, prefix='Nested') context = {'request': self.context['request']} return serializer(obj.scope, context=context).data
class ContactAssignmentSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactassignment-detail') content_type = ContentTypeField( queryset=ContentType.objects.all() ) object = serializers.SerializerMethodField(read_only=True) contact = NestedContactSerializer() role = NestedContactRoleSerializer(required=False, allow_null=True) priority = ChoiceField(choices=ContactPriorityChoices, required=False) class Meta: model = ContactAssignment fields = [ 'id', 'url', 'display', 'content_type', 'object_id', 'object', 'contact', 'role', 'priority', 'created', 'last_updated', ] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_object(self, instance): serializer = get_serializer_for_model(instance.content_type.model_class(), prefix='Nested') context = {'request': self.context['request']} return serializer(instance.object, context=context).data