diff --git a/contrib/openapi.json b/contrib/openapi.json index 34263e6d2..920a07dab 100644 --- a/contrib/openapi.json +++ b/contrib/openapi.json @@ -75760,6 +75760,157 @@ "operationId": "dcim_power_outlet_templates_list", "description": "Get a list of power outlet template objects.", "parameters": [ + { + "in": "query", + "name": "color", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__empty", + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "color__ic", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__ie", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__iew", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__iregex", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__isw", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__n", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__nic", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__nie", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__niew", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__nisw", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, + { + "in": "query", + "name": "color__regex", + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "explode": true, + "style": "form" + }, { "in": "query", "name": "created", @@ -211805,8 +211956,8 @@ "nullable": true }, "termination": { - "nullable": true, - "readOnly": true + "readOnly": true, + "nullable": true }, "port_speed": { "type": "integer", @@ -212009,8 +212160,8 @@ "format": "int64" }, "member": { - "nullable": true, - "readOnly": true + "readOnly": true, + "nullable": true }, "priority": { "type": "object", @@ -212394,8 +212545,8 @@ "nullable": true }, "termination": { - "nullable": true, - "readOnly": true + "readOnly": true, + "nullable": true }, "port_speed": { "type": "integer", @@ -242458,6 +242609,11 @@ "x-spec-enum-id": "8f9617d2648ab261", "nullable": true }, + "color": { + "type": "string", + "pattern": "^[0-9a-f]{6}$", + "maxLength": 6 + }, "power_port": { "oneOf": [ { @@ -247155,6 +247311,11 @@ }, "nullable": true }, + "color": { + "type": "string", + "pattern": "^[0-9a-f]{6}$", + "maxLength": 6 + }, "power_port": { "allOf": [ { @@ -247371,6 +247532,11 @@ "x-spec-enum-id": "8f9617d2648ab261", "nullable": true }, + "color": { + "type": "string", + "pattern": "^[0-9a-f]{6}$", + "maxLength": 6 + }, "power_port": { "oneOf": [ { @@ -264451,6 +264617,11 @@ "x-spec-enum-id": "8f9617d2648ab261", "nullable": true }, + "color": { + "type": "string", + "pattern": "^[0-9a-f]{6}$", + "maxLength": 6 + }, "power_port": { "oneOf": [ { diff --git a/netbox/circuits/api/serializers_/circuits.py b/netbox/circuits/api/serializers_/circuits.py index bc84f66fa..bc86f5271 100644 --- a/netbox/circuits/api/serializers_/circuits.py +++ b/netbox/circuits/api/serializers_/circuits.py @@ -1,5 +1,4 @@ from django.contrib.contenttypes.models import ContentType -from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from circuits.choices import CircuitPriorityChoices, CircuitStatusChoices, VirtualCircuitTerminationRoleChoices @@ -11,12 +10,12 @@ from circuits.models import ( from dcim.api.serializers_.device_components import InterfaceSerializer from dcim.api.serializers_.cables import CabledObjectSerializer from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField +from netbox.api.fields2 import GFKSerializerField from netbox.api.serializers import ( NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, WritableNestedSerializer, ) from netbox.choices import DistanceUnitChoices from tenancy.api.serializers_.tenants import TenantSerializer -from utilities.api import get_serializer_for_model from .providers import ProviderAccountSerializer, ProviderNetworkSerializer, ProviderSerializer __all__ = ( @@ -55,7 +54,7 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer): default=None ) termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) - termination = serializers.SerializerMethodField(read_only=True) + termination = GFKSerializerField() class Meta: model = CircuitTermination @@ -64,14 +63,6 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer): 'upstream_speed', 'xconnect_id', 'description', ] - @extend_schema_field(serializers.JSONField(allow_null=True)) - def get_termination(self, obj): - if obj.termination_id is None: - return None - serializer = get_serializer_for_model(obj.termination) - context = {'request': self.context['request']} - return serializer(obj.termination, nested=True, context=context).data - class CircuitGroupSerializer(OrganizationalModelSerializer): tenant = TenantSerializer(nested=True, required=False, allow_null=True) @@ -134,7 +125,7 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer default=None ) termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) - termination = serializers.SerializerMethodField(read_only=True) + termination = GFKSerializerField() class Meta: model = CircuitTermination @@ -146,20 +137,12 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer ] brief_fields = ('id', 'url', 'display', 'circuit', 'term_side', 'description', 'cable', '_occupied') - @extend_schema_field(serializers.JSONField(allow_null=True)) - def get_termination(self, obj): - if obj.termination_id is None: - return None - serializer = get_serializer_for_model(obj.termination) - context = {'request': self.context['request']} - return serializer(obj.termination, nested=True, context=context).data - class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_): member_type = ContentTypeField( queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS) ) - member = serializers.SerializerMethodField(read_only=True) + member = GFKSerializerField() class Meta: model = CircuitGroupAssignment @@ -169,14 +152,6 @@ class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_): ] brief_fields = ('id', 'url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority') - @extend_schema_field(serializers.JSONField(allow_null=True)) - def get_member(self, obj): - if obj.member_id is None: - return None - serializer = get_serializer_for_model(obj.member) - context = {'request': self.context['request']} - return serializer(obj.member, nested=True, context=context).data - class VirtualCircuitTypeSerializer(OrganizationalModelSerializer): diff --git a/netbox/netbox/api/fields2.py b/netbox/netbox/api/fields2.py new file mode 100644 index 000000000..d2bbeac4c --- /dev/null +++ b/netbox/netbox/api/fields2.py @@ -0,0 +1,18 @@ +from drf_spectacular.utils import extend_schema_field +from rest_framework import serializers +from utilities.api import get_serializer_for_model + +__all__ = ( + 'GFKSerializerField', +) + + +@extend_schema_field(serializers.JSONField(allow_null=True, read_only=True)) +class GFKSerializerField(serializers.Field): + + def to_representation(self, instance, **kwargs): + if instance is None: + return None + serializer = get_serializer_for_model(instance) + context = {'request': self.context['request']} + return serializer(instance, nested=True, context=context).data