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=get_user_model().objects.all(), serializer=NestedUserSerializer, required=False, many=True, ) class Meta: model = ObjectPermission fields = ( "id", "url", "name", "description", "enabled", "object_types", "groups", "users", "actions", "constraints", )
class ServiceSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField( view_name="ipam-api:service-detail") device = NestedDeviceSerializer(required=False, allow_null=True) virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True) protocol = ChoiceField(choices=ServiceProtocolChoices, required=False) ipaddresses = SerializedPKRelatedField( queryset=IPAddress.objects.all(), serializer=NestedIPAddressSerializer, required=False, many=True, ) ports = serializers.ListField(child=serializers.IntegerField( min_value=constants.SERVICE_PORT_MIN, max_value=constants.SERVICE_PORT_MAX, )) class Meta: model = Service fields = [ "id", "url", "device", "virtual_machine", "name", "ports", "protocol", "ipaddresses", "description", "tags", "custom_fields", "created", "last_updated", ]
class VRFSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name="ipam-api:vrf-detail") tenant = NestedTenantSerializer(required=False, allow_null=True) import_targets = SerializedPKRelatedField( queryset=RouteTarget.objects.all(), serializer=NestedRouteTargetSerializer, required=False, many=True, ) export_targets = SerializedPKRelatedField( queryset=RouteTarget.objects.all(), serializer=NestedRouteTargetSerializer, required=False, many=True, ) ipaddress_count = serializers.IntegerField(read_only=True) prefix_count = serializers.IntegerField(read_only=True) class Meta: model = VRF fields = [ "id", "url", "name", "rd", "tenant", "enforce_unique", "description", "import_targets", "export_targets", "tags", "custom_fields", "created", "last_updated", "ipaddress_count", "prefix_count", "computed_fields", ] opt_in_fields = ["computed_fields"]
class VMInterfaceSerializer(TaggedObjectSerializer, ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name="virtualization-api:vminterface-detail") virtual_machine = NestedVirtualMachineSerializer() mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, 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 = VMInterface fields = [ "id", "url", "virtual_machine", "name", "enabled", "mtu", "mac_address", "description", "mode", "untagged_vlan", "tagged_vlans", "tags", ] def validate(self, data): # Validate many-to-many VLAN assignments virtual_machine = self.instance.virtual_machine if self.instance else data.get( "virtual_machine") for vlan in data.get("tagged_vlans", []): if vlan.site not in [virtual_machine.site, None]: raise serializers.ValidationError({ "tagged_vlans": f"VLAN {vlan} must belong to the same site as the interface's parent virtual " f"machine, or it must be global." }) return super().validate(data)
class UserSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name="users-api:user-detail") groups = SerializedPKRelatedField( queryset=Group.objects.all(), serializer=NestedGroupSerializer, required=False, many=True, ) class Meta: model = User fields = ( "id", "url", "username", "password", "first_name", "last_name", "email", "is_staff", "is_active", "date_joined", "groups", ) extra_kwargs = {"password": {"write_only": True}} def create(self, validated_data): """ Extract the password from validated data and set it separately to ensure proper hash generation. """ password = validated_data.pop("password") user = super().create(validated_data) user.set_password(password) user.save() return user
class InterfaceSerializer( TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer, CustomFieldModelSerializer, ): url = serializers.HyperlinkedIdentityField( view_name="dcim-api:interface-detail") device = NestedDeviceSerializer() type = ChoiceField(choices=InterfaceTypeChoices) lag = NestedInterfaceSerializer(required=False, allow_null=True) mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False) untagged_vlan = NestedVLANSerializer(required=False, allow_null=True) tagged_vlans = SerializedPKRelatedField( queryset=VLAN.objects.all(), serializer=NestedVLANSerializer, required=False, many=True, ) cable = NestedCableSerializer(read_only=True) count_ipaddresses = serializers.IntegerField(read_only=True) class Meta: model = Interface fields = [ "id", "url", "device", "name", "label", "type", "enabled", "lag", "mtu", "mac_address", "mgmt_only", "description", "mode", "untagged_vlan", "tagged_vlans", "cable", "cable_peer", "cable_peer_type", "connected_endpoint", "connected_endpoint_type", "connected_endpoint_reachable", "tags", "count_ipaddresses", "custom_fields", "computed_fields", ] opt_in_fields = ["computed_fields"] def validate(self, data): # Validate many-to-many VLAN assignments device = self.instance.device if self.instance else data.get("device") for vlan in data.get("tagged_vlans", []): if vlan.site not in [device.site, None]: raise serializers.ValidationError({ "tagged_vlans": f"VLAN {vlan} must belong to the same site as the interface's parent device, or " f"it must be global." }) return super().validate(data)
class ConfigContextSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name="extras-api:configcontext-detail") owner_content_type = ContentTypeField( queryset=ContentType.objects.filter( FeatureQuery("config_context_owners").get_query()), required=False, allow_null=True, default=None, ) owner = serializers.SerializerMethodField(read_only=True) schema = NestedConfigContextSchemaSerializer(required=False, allow_null=True) regions = SerializedPKRelatedField( queryset=Region.objects.all(), serializer=NestedRegionSerializer, required=False, many=True, ) sites = SerializedPKRelatedField( queryset=Site.objects.all(), serializer=NestedSiteSerializer, required=False, many=True, ) roles = SerializedPKRelatedField( queryset=DeviceRole.objects.all(), serializer=NestedDeviceRoleSerializer, required=False, many=True, ) device_types = SerializedPKRelatedField( queryset=DeviceType.objects.all(), serializer=NestedDeviceRoleSerializer, required=False, many=True, ) platforms = SerializedPKRelatedField( queryset=Platform.objects.all(), serializer=NestedPlatformSerializer, required=False, many=True, ) cluster_groups = SerializedPKRelatedField( queryset=ClusterGroup.objects.all(), serializer=NestedClusterGroupSerializer, required=False, many=True, ) clusters = SerializedPKRelatedField( queryset=Cluster.objects.all(), serializer=NestedClusterSerializer, required=False, many=True, ) tenant_groups = SerializedPKRelatedField( queryset=TenantGroup.objects.all(), serializer=NestedTenantGroupSerializer, required=False, many=True, ) tenants = SerializedPKRelatedField( queryset=Tenant.objects.all(), serializer=NestedTenantSerializer, required=False, many=True, ) tags = serializers.SlugRelatedField(queryset=Tag.objects.all(), slug_field="slug", required=False, many=True) class Meta: model = ConfigContext fields = [ "id", "url", "name", "owner_content_type", "owner_object_id", "owner", "weight", "description", "schema", "is_active", "regions", "sites", "roles", "device_types", "platforms", "cluster_groups", "clusters", "tenant_groups", "tenants", "tags", "data", "created", "last_updated", ] @swagger_serializer_method(serializer_or_field=serializers.DictField) def get_owner(self, obj): if obj.owner is None: return None serializer = get_serializer_for_model(obj.owner, prefix="Nested") context = {"request": self.context["request"]} return serializer(obj.owner, context=context).data