Closes: #17936 - GFK serializer field (#20706)
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled

* Establish GFKSerializerField and replace get_* methods in circuits.py

* Set read_only=True

* Apply GFKSerializerField to all matching SerializerMethodFields

* Use GFKSerializerField for ObjectChangeSerializer.changed_object and EventRuleSerializer.action_object
This commit is contained in:
bctiemann
2025-11-04 10:01:22 -05:00
committed by GitHub
parent 068d493cc6
commit bcffc383bf
22 changed files with 119 additions and 318 deletions

View File

@@ -206935,8 +206935,8 @@
"format": "int64" "format": "int64"
}, },
"object": { "object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"user": { "user": {
"$ref": "#/components/schemas/BriefUser" "$ref": "#/components/schemas/BriefUser"
@@ -211700,8 +211700,8 @@
"readOnly": true "readOnly": true
}, },
"termination": { "termination": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"created": { "created": {
"type": "string", "type": "string",
@@ -211972,8 +211972,8 @@
"nullable": true "nullable": true
}, },
"termination": { "termination": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"port_speed": { "port_speed": {
"type": "integer", "type": "integer",
@@ -212176,8 +212176,8 @@
"format": "int64" "format": "int64"
}, },
"member": { "member": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"priority": { "priority": {
"type": "object", "type": "object",
@@ -212561,8 +212561,8 @@
"nullable": true "nullable": true
}, },
"termination": { "termination": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"port_speed": { "port_speed": {
"type": "integer", "type": "integer",
@@ -212978,8 +212978,8 @@
"nullable": true "nullable": true
}, },
"scope": { "scope": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"description": { "description": {
"type": "string", "type": "string",
@@ -215293,9 +215293,8 @@
"format": "int64" "format": "int64"
}, },
"object": { "object": {
"type": "object", "readOnly": true,
"additionalProperties": {}, "nullable": true
"readOnly": true
}, },
"contact": { "contact": {
"$ref": "#/components/schemas/BriefContact" "$ref": "#/components/schemas/BriefContact"
@@ -219029,9 +219028,8 @@
"nullable": true "nullable": true
}, },
"action_object": { "action_object": {
"type": "object", "readOnly": true,
"additionalProperties": {}, "nullable": true
"readOnly": true
}, },
"description": { "description": {
"type": "string", "type": "string",
@@ -219536,8 +219534,8 @@
"format": "int64" "format": "int64"
}, },
"interface": { "interface": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"priority": { "priority": {
"type": "integer", "type": "integer",
@@ -221339,8 +221337,8 @@
"nullable": true "nullable": true
}, },
"assigned_object": { "assigned_object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"nat_inside": { "nat_inside": {
"allOf": [ "allOf": [
@@ -222501,8 +222499,8 @@
"format": "int64" "format": "int64"
}, },
"parent": { "parent": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"name": { "name": {
"type": "string", "type": "string",
@@ -225660,8 +225658,8 @@
"nullable": true "nullable": true
}, },
"component": { "component": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"tags": { "tags": {
"type": "array", "type": "array",
@@ -226044,8 +226042,8 @@
"nullable": true "nullable": true
}, },
"component": { "component": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"created": { "created": {
"type": "string", "type": "string",
@@ -226327,8 +226325,8 @@
"format": "int64" "format": "int64"
}, },
"assigned_object": { "assigned_object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"created": { "created": {
"type": "string", "type": "string",
@@ -226777,8 +226775,8 @@
"format": "int64" "format": "int64"
}, },
"assigned_object": { "assigned_object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"tags": { "tags": {
"type": "array", "type": "array",
@@ -227155,8 +227153,8 @@
"nullable": true "nullable": true
}, },
"assigned_object": { "assigned_object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"description": { "description": {
"type": "string", "type": "string",
@@ -229542,8 +229540,8 @@
"format": "int64" "format": "int64"
}, },
"object": { "object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"user": { "user": {
"$ref": "#/components/schemas/BriefUser" "$ref": "#/components/schemas/BriefUser"
@@ -229796,7 +229794,11 @@
"format": "int64" "format": "int64"
}, },
"changed_object": { "changed_object": {
"nullable": true, "readOnly": true,
"nullable": true
},
"object_repr": {
"type": "string",
"readOnly": true "readOnly": true
}, },
"message": { "message": {
@@ -229821,6 +229823,7 @@
"display_url", "display_url",
"id", "id",
"message", "message",
"object_repr",
"postchange_data", "postchange_data",
"prechange_data", "prechange_data",
"request_id", "request_id",
@@ -248892,8 +248895,8 @@
"nullable": true "nullable": true
}, },
"scope": { "scope": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"tenant": { "tenant": {
"allOf": [ "allOf": [
@@ -252745,8 +252748,8 @@
"format": "int64" "format": "int64"
}, },
"parent": { "parent": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"name": { "name": {
"type": "string", "type": "string",
@@ -253669,8 +253672,8 @@
"format": "int64" "format": "int64"
}, },
"object": { "object": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"user": { "user": {
"$ref": "#/components/schemas/BriefUser" "$ref": "#/components/schemas/BriefUser"
@@ -255193,8 +255196,8 @@
"nullable": true "nullable": true
}, },
"termination": { "termination": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"outside_ip": { "outside_ip": {
"allOf": [ "allOf": [
@@ -255671,8 +255674,8 @@
"nullable": true "nullable": true
}, },
"scope": { "scope": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"vid_ranges": { "vid_ranges": {
"type": "array", "type": "array",
@@ -258528,8 +258531,8 @@
"nullable": true "nullable": true
}, },
"scope": { "scope": {
"nullable": true, "readOnly": true,
"readOnly": true "nullable": true
}, },
"tenant": { "tenant": {
"allOf": [ "allOf": [

View File

@@ -1,5 +1,4 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from circuits.choices import CircuitPriorityChoices, CircuitStatusChoices, VirtualCircuitTerminationRoleChoices 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_.device_components import InterfaceSerializer
from dcim.api.serializers_.cables import CabledObjectSerializer from dcim.api.serializers_.cables import CabledObjectSerializer
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ( from netbox.api.serializers import (
NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, WritableNestedSerializer, NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, WritableNestedSerializer,
) )
from netbox.choices import DistanceUnitChoices from netbox.choices import DistanceUnitChoices
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from .providers import ProviderAccountSerializer, ProviderNetworkSerializer, ProviderSerializer from .providers import ProviderAccountSerializer, ProviderNetworkSerializer, ProviderSerializer
__all__ = ( __all__ = (
@@ -55,7 +54,7 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer):
default=None default=None
) )
termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) termination_id = serializers.IntegerField(allow_null=True, required=False, default=None)
termination = serializers.SerializerMethodField(read_only=True) termination = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = CircuitTermination model = CircuitTermination
@@ -64,14 +63,6 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer):
'upstream_speed', 'xconnect_id', 'description', '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): class CircuitGroupSerializer(OrganizationalModelSerializer):
tenant = TenantSerializer(nested=True, required=False, allow_null=True) tenant = TenantSerializer(nested=True, required=False, allow_null=True)
@@ -134,7 +125,7 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer
default=None default=None
) )
termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) termination_id = serializers.IntegerField(allow_null=True, required=False, default=None)
termination = serializers.SerializerMethodField(read_only=True) termination = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = CircuitTermination model = CircuitTermination
@@ -146,20 +137,12 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer
] ]
brief_fields = ('id', 'url', 'display', 'circuit', 'term_side', 'description', 'cable', '_occupied') 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_): class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_):
member_type = ContentTypeField( member_type = ContentTypeField(
queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS) queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS)
) )
member = serializers.SerializerMethodField(read_only=True) member = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = CircuitGroupAssignment model = CircuitGroupAssignment
@@ -169,14 +152,6 @@ class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_):
] ]
brief_fields = ('id', 'url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority') 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): class VirtualCircuitTypeSerializer(OrganizationalModelSerializer):

View File

@@ -1,13 +1,11 @@
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from core.choices import * from core.choices import *
from core.models import ObjectChange from core.models import ObjectChange
from netbox.api.exceptions import SerializerNotFound
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import BaseModelSerializer from netbox.api.serializers import BaseModelSerializer
from users.api.serializers_.users import UserSerializer from users.api.serializers_.users import UserSerializer
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'ObjectChangeSerializer', 'ObjectChangeSerializer',
@@ -26,7 +24,10 @@ class ObjectChangeSerializer(BaseModelSerializer):
changed_object_type = ContentTypeField( changed_object_type = ContentTypeField(
read_only=True read_only=True
) )
changed_object = serializers.SerializerMethodField( changed_object = GFKSerializerField(
read_only=True
)
object_repr = serializers.CharField(
read_only=True read_only=True
) )
prechange_data = serializers.JSONField( prechange_data = serializers.JSONField(
@@ -44,22 +45,6 @@ class ObjectChangeSerializer(BaseModelSerializer):
model = ObjectChange model = ObjectChange
fields = [ fields = [
'id', 'url', 'display_url', 'display', 'time', 'user', 'user_name', 'request_id', 'action', 'id', 'url', 'display_url', 'display', 'time', 'user', 'user_name', 'request_id', 'action',
'changed_object_type', 'changed_object_id', 'changed_object', 'message', 'prechange_data', 'changed_object_type', 'changed_object_id', 'changed_object', 'object_repr', 'message',
'postchange_data', 'prechange_data', 'postchange_data',
] ]
@extend_schema_field(serializers.JSONField(allow_null=True))
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)
except SerializerNotFound:
return obj.object_repr
data = serializer(obj.changed_object, nested=True, context={'request': self.context['request']}).data
return data

View File

@@ -5,6 +5,7 @@ from rest_framework import serializers
from dcim.choices import * from dcim.choices import *
from dcim.models import Cable, CablePath, CableTermination from dcim.models import Cable, CablePath, CableTermination
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ( from netbox.api.serializers import (
BaseModelSerializer, GenericObjectSerializer, NetBoxModelSerializer, PrimaryModelSerializer, BaseModelSerializer, GenericObjectSerializer, NetBoxModelSerializer, PrimaryModelSerializer,
) )
@@ -53,9 +54,7 @@ class CableTerminationSerializer(NetBoxModelSerializer):
termination_type = ContentTypeField( termination_type = ContentTypeField(
read_only=True, read_only=True,
) )
termination = serializers.SerializerMethodField( termination = GFKSerializerField(read_only=True)
read_only=True,
)
class Meta: class Meta:
model = CableTermination model = CableTermination
@@ -66,12 +65,6 @@ class CableTerminationSerializer(NetBoxModelSerializer):
read_only_fields = fields read_only_fields = fields
brief_fields = ('id', 'url', 'display', 'cable', 'cable_end', 'termination_type', 'termination_id') brief_fields = ('id', 'url', 'display', 'cable', 'cable_end', 'termination_type', 'termination_id')
@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): class CablePathSerializer(serializers.ModelSerializer):
path = serializers.SerializerMethodField(read_only=True) path = serializers.SerializerMethodField(read_only=True)

View File

@@ -1,6 +1,5 @@
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from dcim.choices import * from dcim.choices import *
@@ -13,8 +12,8 @@ from ipam.api.serializers_.vlans import VLANSerializer, VLANTranslationPolicySer
from ipam.api.serializers_.vrfs import VRFSerializer from ipam.api.serializers_.vrfs import VRFSerializer
from ipam.models import VLAN from ipam.models import VLAN
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
from utilities.api import get_serializer_for_model
from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
from wireless.api.serializers_.nested import NestedWirelessLinkSerializer from wireless.api.serializers_.nested import NestedWirelessLinkSerializer
from wireless.api.serializers_.wirelesslans import WirelessLANSerializer from wireless.api.serializers_.wirelesslans import WirelessLANSerializer
@@ -394,7 +393,7 @@ class InventoryItemSerializer(NetBoxModelSerializer):
required=False, required=False,
allow_null=True allow_null=True
) )
component = serializers.SerializerMethodField(read_only=True, allow_null=True) component = GFKSerializerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True) _depth = serializers.IntegerField(source='level', read_only=True)
status = ChoiceField(choices=InventoryItemStatusChoices, required=False) status = ChoiceField(choices=InventoryItemStatusChoices, required=False)
@@ -406,11 +405,3 @@ class InventoryItemSerializer(NetBoxModelSerializer):
'component_id', 'component', 'tags', 'custom_fields', 'created', 'last_updated', '_depth', 'component_id', 'component', 'tags', 'custom_fields', 'created', 'last_updated', '_depth',
] ]
brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', '_depth') brief_fields = ('id', 'url', 'display', 'device', 'name', 'description', '_depth')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_component(self, obj):
if obj.component is None:
return None
serializer = get_serializer_for_model(obj.component)
context = {'request': self.context['request']}
return serializer(obj.component, nested=True, context=context).data

View File

@@ -11,9 +11,9 @@ from dcim.models import Device, DeviceBay, MACAddress, Module, VirtualDeviceCont
from extras.api.serializers_.configtemplates import ConfigTemplateSerializer from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
from ipam.api.serializers_.ip import IPAddressSerializer from ipam.api.serializers_.ip import IPAddressSerializer
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import PrimaryModelSerializer from netbox.api.serializers import PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from virtualization.api.serializers_.clusters import ClusterSerializer from virtualization.api.serializers_.clusters import ClusterSerializer
from .devicetypes import * from .devicetypes import *
from .nested import NestedDeviceBaySerializer, NestedDeviceSerializer, NestedModuleBaySerializer from .nested import NestedDeviceBaySerializer, NestedDeviceSerializer, NestedModuleBaySerializer
@@ -165,7 +165,7 @@ class MACAddressSerializer(PrimaryModelSerializer):
required=False, required=False,
allow_null=True allow_null=True
) )
assigned_object = serializers.SerializerMethodField(read_only=True) assigned_object = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = MACAddress model = MACAddress
@@ -174,11 +174,3 @@ class MACAddressSerializer(PrimaryModelSerializer):
'assigned_object', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'assigned_object', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'mac_address', 'description') brief_fields = ('id', 'url', 'display', 'mac_address', 'description')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_assigned_object(self, obj):
if obj.assigned_object is None:
return None
serializer = get_serializer_for_model(obj.assigned_object)
context = {'request': self.context['request']}
return serializer(obj.assigned_object, nested=True, context=context).data

View File

@@ -1,5 +1,4 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from dcim.choices import * from dcim.choices import *
@@ -9,8 +8,8 @@ from dcim.models import (
InventoryItemTemplate, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate, InventoryItemTemplate, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate,
) )
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
from utilities.api import get_serializer_for_model
from wireless.choices import * from wireless.choices import *
from .devicetypes import DeviceTypeSerializer, ModuleTypeSerializer from .devicetypes import DeviceTypeSerializer, ModuleTypeSerializer
from .manufacturers import ManufacturerSerializer from .manufacturers import ManufacturerSerializer
@@ -313,7 +312,7 @@ class InventoryItemTemplateSerializer(ComponentTemplateSerializer):
required=False, required=False,
allow_null=True allow_null=True
) )
component = serializers.SerializerMethodField(read_only=True, allow_null=True) component = GFKSerializerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True) _depth = serializers.IntegerField(source='level', read_only=True)
class Meta: class Meta:
@@ -324,11 +323,3 @@ class InventoryItemTemplateSerializer(ComponentTemplateSerializer):
'_depth', '_depth',
] ]
brief_fields = ('id', 'url', 'display', 'name', 'description', '_depth') brief_fields = ('id', 'url', 'display', 'name', 'description', '_depth')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_component(self, obj):
if obj.component is None:
return None
serializer = get_serializer_for_model(obj.component)
context = {'request': self.context['request']}
return serializer(obj.component, nested=True, context=context).data

View File

@@ -1,12 +1,11 @@
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from extras.models import ImageAttachment from extras.models import ImageAttachment
from netbox.api.fields import ContentTypeField from netbox.api.fields import ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ValidatedModelSerializer from netbox.api.serializers import ValidatedModelSerializer
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'ImageAttachmentSerializer', 'ImageAttachmentSerializer',
@@ -17,7 +16,7 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
object_type = ContentTypeField( object_type = ContentTypeField(
queryset=ObjectType.objects.all() queryset=ObjectType.objects.all()
) )
parent = serializers.SerializerMethodField(read_only=True) parent = GFKSerializerField(read_only=True)
image_width = serializers.IntegerField(read_only=True) image_width = serializers.IntegerField(read_only=True)
image_height = serializers.IntegerField(read_only=True) image_height = serializers.IntegerField(read_only=True)
@@ -43,9 +42,3 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
super().validate(data) super().validate(data)
return data return data
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_parent(self, obj):
serializer = get_serializer_for_model(obj.parent)
context = {'request': self.context['request']}
return serializer(obj.parent, nested=True, context=context).data

View File

@@ -1,12 +1,9 @@
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from extras.models import Bookmark from extras.models import Bookmark
from netbox.api.fields import ContentTypeField from netbox.api.fields import ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ValidatedModelSerializer from netbox.api.serializers import ValidatedModelSerializer
from users.api.serializers_.users import UserSerializer from users.api.serializers_.users import UserSerializer
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'BookmarkSerializer', 'BookmarkSerializer',
@@ -17,7 +14,7 @@ class BookmarkSerializer(ValidatedModelSerializer):
object_type = ContentTypeField( object_type = ContentTypeField(
queryset=ObjectType.objects.with_feature('bookmarks'), queryset=ObjectType.objects.with_feature('bookmarks'),
) )
object = serializers.SerializerMethodField(read_only=True) object = GFKSerializerField(read_only=True)
user = UserSerializer(nested=True) user = UserSerializer(nested=True)
class Meta: class Meta:
@@ -26,9 +23,3 @@ class BookmarkSerializer(ValidatedModelSerializer):
'id', 'url', 'display', 'object_type', 'object_id', 'object', 'user', 'created', 'id', 'url', 'display', 'object_type', 'object_id', 'object', 'user', 'created',
] ]
brief_fields = ('id', 'url', 'display', 'object_id', 'object_type') brief_fields = ('id', 'url', 'display', 'object_id', 'object_type')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_object(self, instance):
serializer = get_serializer_for_model(instance.object)
context = {'request': self.context['request']}
return serializer(instance.object, nested=True, context=context).data

View File

@@ -1,15 +1,10 @@
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from extras.choices import * from extras.choices import *
from extras.models import EventRule, Webhook from extras.models import EventRule, Webhook
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer from netbox.api.serializers import NetBoxModelSerializer
from users.api.serializers_.mixins import OwnerMixin from users.api.serializers_.mixins import OwnerMixin
from utilities.api import get_serializer_for_model
from .scripts import ScriptSerializer
__all__ = ( __all__ = (
'EventRuleSerializer', 'EventRuleSerializer',
@@ -30,7 +25,7 @@ class EventRuleSerializer(OwnerMixin, NetBoxModelSerializer):
action_object_type = ContentTypeField( action_object_type = ContentTypeField(
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
) )
action_object = serializers.SerializerMethodField(read_only=True) action_object = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = EventRule model = EventRule
@@ -41,17 +36,6 @@ class EventRuleSerializer(OwnerMixin, NetBoxModelSerializer):
] ]
brief_fields = ('id', 'url', 'display', 'name', 'description') brief_fields = ('id', 'url', 'display', 'name', 'description')
@extend_schema_field(OpenApiTypes.OBJECT)
def get_action_object(self, instance):
context = {'request': self.context['request']}
# We need to manually instantiate the serializer for scripts
if instance.action_type == EventRuleActionChoices.SCRIPT:
script = instance.action_object
return ScriptSerializer(script, nested=True, context=context).data
else:
serializer = get_serializer_for_model(instance.action_object_type.model_class())
return serializer(instance.action_object, nested=True, context=context).data
# #
# Webhooks # Webhooks

View File

@@ -1,14 +1,13 @@
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from extras.choices import * from extras.choices import *
from extras.models import JournalEntry from extras.models import JournalEntry
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer from netbox.api.serializers import NetBoxModelSerializer
from users.models import User from users.models import User
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'JournalEntrySerializer', 'JournalEntrySerializer',
@@ -19,7 +18,7 @@ class JournalEntrySerializer(NetBoxModelSerializer):
assigned_object_type = ContentTypeField( assigned_object_type = ContentTypeField(
queryset=ObjectType.objects.all() queryset=ObjectType.objects.all()
) )
assigned_object = serializers.SerializerMethodField(read_only=True) assigned_object = GFKSerializerField(read_only=True)
created_by = serializers.PrimaryKeyRelatedField( created_by = serializers.PrimaryKeyRelatedField(
allow_null=True, allow_null=True,
queryset=User.objects.all(), queryset=User.objects.all(),
@@ -51,9 +50,3 @@ class JournalEntrySerializer(NetBoxModelSerializer):
) )
return super().validate(data) return super().validate(data)
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_assigned_object(self, instance):
serializer = get_serializer_for_model(instance.assigned_object_type.model_class())
context = {'request': self.context['request']}
return serializer(instance.assigned_object, nested=True, context=context).data

View File

@@ -1,13 +1,10 @@
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from extras.models import Notification, NotificationGroup, Subscription from extras.models import Notification, NotificationGroup, Subscription
from netbox.api.fields import ContentTypeField, SerializedPKRelatedField from netbox.api.fields import ContentTypeField, SerializedPKRelatedField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer
from users.api.serializers_.users import GroupSerializer, UserSerializer from users.api.serializers_.users import GroupSerializer, UserSerializer
from users.models import Group, User from users.models import Group, User
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'NotificationSerializer', 'NotificationSerializer',
@@ -20,7 +17,7 @@ class NotificationSerializer(ValidatedModelSerializer):
object_type = ContentTypeField( object_type = ContentTypeField(
queryset=ObjectType.objects.with_feature('notifications'), queryset=ObjectType.objects.with_feature('notifications'),
) )
object = serializers.SerializerMethodField(read_only=True) object = GFKSerializerField(read_only=True)
user = UserSerializer(nested=True) user = UserSerializer(nested=True)
class Meta: class Meta:
@@ -30,12 +27,6 @@ class NotificationSerializer(ValidatedModelSerializer):
] ]
brief_fields = ('id', 'url', 'display', 'object_type', 'object_id', 'user', 'read', 'event_type') brief_fields = ('id', 'url', 'display', 'object_type', 'object_id', 'user', 'read', 'event_type')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_object(self, instance):
serializer = get_serializer_for_model(instance.object)
context = {'request': self.context['request']}
return serializer(instance.object, nested=True, context=context).data
class NotificationGroupSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer): class NotificationGroupSerializer(ChangeLogMessageSerializer, ValidatedModelSerializer):
groups = SerializedPKRelatedField( groups = SerializedPKRelatedField(
@@ -65,7 +56,7 @@ class SubscriptionSerializer(ValidatedModelSerializer):
object_type = ContentTypeField( object_type = ContentTypeField(
queryset=ObjectType.objects.with_feature('notifications'), queryset=ObjectType.objects.with_feature('notifications'),
) )
object = serializers.SerializerMethodField(read_only=True) object = GFKSerializerField(read_only=True)
user = UserSerializer(nested=True) user = UserSerializer(nested=True)
class Meta: class Meta:
@@ -74,9 +65,3 @@ class SubscriptionSerializer(ValidatedModelSerializer):
'id', 'url', 'display', 'object_type', 'object_id', 'object', 'user', 'created', 'id', 'url', 'display', 'object_type', 'object_id', 'object', 'user', 'created',
] ]
brief_fields = ('id', 'url', 'display', 'object_type', 'object_id', 'user') brief_fields = ('id', 'url', 'display', 'object_type', 'object_id', 'user')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_object(self, instance):
serializer = get_serializer_for_model(instance.object)
context = {'request': self.context['request']}
return serializer(instance.object, nested=True, context=context).data

View File

@@ -1,11 +1,8 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from ipam.models import FHRPGroup, FHRPGroupAssignment from ipam.models import FHRPGroup, FHRPGroupAssignment
from netbox.api.fields import ContentTypeField from netbox.api.fields import ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
from utilities.api import get_serializer_for_model
from .ip import IPAddressSerializer from .ip import IPAddressSerializer
__all__ = ( __all__ = (
@@ -31,7 +28,7 @@ class FHRPGroupAssignmentSerializer(NetBoxModelSerializer):
interface_type = ContentTypeField( interface_type = ContentTypeField(
queryset=ContentType.objects.all() queryset=ContentType.objects.all()
) )
interface = serializers.SerializerMethodField(read_only=True) interface = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = FHRPGroupAssignment model = FHRPGroupAssignment
@@ -40,11 +37,3 @@ class FHRPGroupAssignmentSerializer(NetBoxModelSerializer):
'priority', 'created', 'last_updated', 'priority', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'group', 'interface_type', 'interface_id', 'priority') brief_fields = ('id', 'url', 'display', 'group', 'interface_type', 'interface_id', 'priority')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_interface(self, obj):
if obj.interface is None:
return None
serializer = get_serializer_for_model(obj.interface)
context = {'request': self.context['request']}
return serializer(obj.interface, nested=True, context=context).data

View File

@@ -1,5 +1,4 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from dcim.constants import LOCATION_SCOPE_TYPES from dcim.constants import LOCATION_SCOPE_TYPES
@@ -7,9 +6,9 @@ from ipam.choices import *
from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
from ipam.models import Aggregate, IPAddress, IPRange, Prefix from ipam.models import Aggregate, IPAddress, IPRange, Prefix
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import PrimaryModelSerializer from netbox.api.serializers import PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from .asns import RIRSerializer from .asns import RIRSerializer
from .nested import NestedIPAddressSerializer from .nested import NestedIPAddressSerializer
from .roles import RoleSerializer from .roles import RoleSerializer
@@ -55,7 +54,7 @@ class PrefixSerializer(PrimaryModelSerializer):
default=None default=None
) )
scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
scope = serializers.SerializerMethodField(read_only=True) scope = GFKSerializerField(read_only=True)
tenant = TenantSerializer(nested=True, required=False, allow_null=True) tenant = TenantSerializer(nested=True, required=False, allow_null=True)
vlan = VLANSerializer(nested=True, required=False, allow_null=True) vlan = VLANSerializer(nested=True, required=False, allow_null=True)
status = ChoiceField(choices=PrefixStatusChoices, required=False) status = ChoiceField(choices=PrefixStatusChoices, required=False)
@@ -73,14 +72,6 @@ class PrefixSerializer(PrimaryModelSerializer):
] ]
brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth') brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_scope(self, obj):
if obj.scope_id is None:
return None
serializer = get_serializer_for_model(obj.scope)
context = {'request': self.context['request']}
return serializer(obj.scope, nested=True, context=context).data
class PrefixLengthSerializer(serializers.Serializer): class PrefixLengthSerializer(serializers.Serializer):
@@ -168,7 +159,7 @@ class IPAddressSerializer(PrimaryModelSerializer):
required=False, required=False,
allow_null=True allow_null=True
) )
assigned_object = serializers.SerializerMethodField(read_only=True) assigned_object = GFKSerializerField(read_only=True)
nat_inside = NestedIPAddressSerializer(required=False, allow_null=True) nat_inside = NestedIPAddressSerializer(required=False, allow_null=True)
nat_outside = NestedIPAddressSerializer(many=True, read_only=True) nat_outside = NestedIPAddressSerializer(many=True, read_only=True)
@@ -181,14 +172,6 @@ class IPAddressSerializer(PrimaryModelSerializer):
] ]
brief_fields = ('id', 'url', 'display', 'family', 'address', 'description') brief_fields = ('id', 'url', 'display', 'family', 'address', 'description')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_assigned_object(self, obj):
if obj.assigned_object is None:
return None
serializer = get_serializer_for_model(obj.assigned_object)
context = {'request': self.context['request']}
return serializer(obj.assigned_object, nested=True, context=context).data
class AvailableIPSerializer(serializers.Serializer): class AvailableIPSerializer(serializers.Serializer):
""" """

View File

@@ -1,13 +1,11 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from ipam.choices import * from ipam.choices import *
from ipam.constants import SERVICE_ASSIGNMENT_MODELS from ipam.constants import SERVICE_ASSIGNMENT_MODELS
from ipam.models import IPAddress, Service, ServiceTemplate from ipam.models import IPAddress, Service, ServiceTemplate
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import PrimaryModelSerializer from netbox.api.serializers import PrimaryModelSerializer
from utilities.api import get_serializer_for_model
from .ip import IPAddressSerializer from .ip import IPAddressSerializer
__all__ = ( __all__ = (
@@ -40,7 +38,7 @@ class ServiceSerializer(PrimaryModelSerializer):
parent_object_type = ContentTypeField( parent_object_type = ContentTypeField(
queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS) queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS)
) )
parent = serializers.SerializerMethodField(read_only=True) parent = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = Service model = Service
@@ -50,11 +48,3 @@ class ServiceSerializer(PrimaryModelSerializer):
'created', 'last_updated', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports', 'description') brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports', 'description')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_parent(self, obj):
if obj.parent is None:
return None
serializer = get_serializer_for_model(obj.parent)
context = {'request': self.context['request']}
return serializer(obj.parent, nested=True, context=context).data

View File

@@ -1,5 +1,4 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from dcim.api.serializers_.sites import SiteSerializer from dcim.api.serializers_.sites import SiteSerializer
@@ -7,9 +6,9 @@ from ipam.choices import *
from ipam.constants import VLANGROUP_SCOPE_TYPES from ipam.constants import VLANGROUP_SCOPE_TYPES
from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VLANTranslationRule from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VLANTranslationRule
from netbox.api.fields import ChoiceField, ContentTypeField, IntegerRangeSerializer, RelatedObjectCountField from netbox.api.fields import ChoiceField, ContentTypeField, IntegerRangeSerializer, RelatedObjectCountField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer
from .nested import NestedVLANSerializer from .nested import NestedVLANSerializer
from .roles import RoleSerializer from .roles import RoleSerializer
@@ -34,7 +33,7 @@ class VLANGroupSerializer(OrganizationalModelSerializer):
default=None default=None
) )
scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
scope = serializers.SerializerMethodField(read_only=True) scope = GFKSerializerField(read_only=True)
vid_ranges = IntegerRangeSerializer(many=True, required=False) vid_ranges = IntegerRangeSerializer(many=True, required=False)
utilization = serializers.CharField(read_only=True) utilization = serializers.CharField(read_only=True)
tenant = TenantSerializer(nested=True, required=False, allow_null=True) tenant = TenantSerializer(nested=True, required=False, allow_null=True)
@@ -52,14 +51,6 @@ class VLANGroupSerializer(OrganizationalModelSerializer):
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'vlan_count') brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'vlan_count')
validators = [] validators = []
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_scope(self, obj):
if obj.scope_id is None:
return None
serializer = get_serializer_for_model(obj.scope)
context = {'request': self.context['request']}
return serializer(obj.scope, nested=True, context=context).data
class VLANSerializer(PrimaryModelSerializer): class VLANSerializer(PrimaryModelSerializer):
site = SiteSerializer(nested=True, required=False, allow_null=True) site = SiteSerializer(nested=True, required=False, allow_null=True)

View File

@@ -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

View File

@@ -1,15 +1,13 @@
from django.contrib.auth.models import ContentType from django.contrib.auth.models import ContentType
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import ( from netbox.api.serializers import (
NestedGroupModelSerializer, NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer, NestedGroupModelSerializer, NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer,
) )
from tenancy.choices import ContactPriorityChoices from tenancy.choices import ContactPriorityChoices
from tenancy.models import ContactAssignment, Contact, ContactGroup, ContactRole from tenancy.models import ContactAssignment, Contact, ContactGroup, ContactRole
from utilities.api import get_serializer_for_model
from .nested import NestedContactGroupSerializer from .nested import NestedContactGroupSerializer
__all__ = ( __all__ = (
@@ -66,7 +64,7 @@ class ContactAssignmentSerializer(NetBoxModelSerializer):
object_type = ContentTypeField( object_type = ContentTypeField(
queryset=ContentType.objects.all() queryset=ContentType.objects.all()
) )
object = serializers.SerializerMethodField(read_only=True) object = GFKSerializerField(read_only=True)
contact = ContactSerializer(nested=True) contact = ContactSerializer(nested=True)
role = ContactRoleSerializer(nested=True, required=False, allow_null=True) role = ContactRoleSerializer(nested=True, required=False, allow_null=True)
priority = ChoiceField(choices=ContactPriorityChoices, allow_blank=True, required=False, default=lambda: '') priority = ChoiceField(choices=ContactPriorityChoices, allow_blank=True, required=False, default=lambda: '')
@@ -78,9 +76,3 @@ class ContactAssignmentSerializer(NetBoxModelSerializer):
'tags', 'custom_fields', 'created', 'last_updated', 'tags', 'custom_fields', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'contact', 'role', 'priority') brief_fields = ('id', 'url', 'display', 'contact', 'role', 'priority')
@extend_schema_field(OpenApiTypes.OBJECT)
def get_object(self, instance):
serializer = get_serializer_for_model(instance.object_type.model_class())
context = {'request': self.context['request']}
return serializer(instance.object, nested=True, context=context).data

View File

@@ -1,13 +1,12 @@
from dcim.constants import LOCATION_SCOPE_TYPES from dcim.constants import LOCATION_SCOPE_TYPES
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from virtualization.choices import * from virtualization.choices import *
from virtualization.models import Cluster, ClusterGroup, ClusterType from virtualization.models import Cluster, ClusterGroup, ClusterType
from utilities.api import get_serializer_for_model
__all__ = ( __all__ = (
'ClusterGroupSerializer', 'ClusterGroupSerializer',
@@ -58,7 +57,7 @@ class ClusterSerializer(PrimaryModelSerializer):
default=None default=None
) )
scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
scope = serializers.SerializerMethodField(read_only=True) scope = GFKSerializerField(read_only=True)
allocated_vcpus = serializers.DecimalField( allocated_vcpus = serializers.DecimalField(
read_only=True, read_only=True,
max_digits=8, max_digits=8,
@@ -80,11 +79,3 @@ class ClusterSerializer(PrimaryModelSerializer):
'device_count', 'virtualmachine_count', 'allocated_vcpus', 'allocated_memory', 'allocated_disk' 'device_count', 'virtualmachine_count', 'allocated_vcpus', 'allocated_memory', 'allocated_disk'
] ]
brief_fields = ('id', 'url', 'display', 'name', 'description', 'virtualmachine_count') brief_fields = ('id', 'url', 'display', 'name', 'description', 'virtualmachine_count')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_scope(self, obj):
if obj.scope_id is None:
return None
serializer = get_serializer_for_model(obj.scope)
context = {'request': self.context['request']}
return serializer(obj.scope, nested=True, context=context).data

View File

@@ -1,13 +1,11 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from ipam.api.serializers_.vrfs import RouteTargetSerializer from ipam.api.serializers_.vrfs import RouteTargetSerializer
from ipam.models import RouteTarget from ipam.models import RouteTarget
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from vpn.choices import * from vpn.choices import *
from vpn.models import L2VPN, L2VPNTermination from vpn.models import L2VPN, L2VPNTermination
@@ -53,7 +51,7 @@ class L2VPNTerminationSerializer(NetBoxModelSerializer):
assigned_object_type = ContentTypeField( assigned_object_type = ContentTypeField(
queryset=ContentType.objects.all() queryset=ContentType.objects.all()
) )
assigned_object = serializers.SerializerMethodField(read_only=True) assigned_object = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = L2VPNTermination model = L2VPNTermination
@@ -62,9 +60,3 @@ class L2VPNTerminationSerializer(NetBoxModelSerializer):
'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated' 'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated'
] ]
brief_fields = ('id', 'url', 'display', 'l2vpn') brief_fields = ('id', 'url', 'display', 'l2vpn')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_assigned_object(self, instance):
serializer = get_serializer_for_model(instance.assigned_object)
context = {'request': self.context['request']}
return serializer(instance.assigned_object, nested=True, context=context).data

View File

@@ -1,12 +1,10 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from ipam.api.serializers_.ip import IPAddressSerializer from ipam.api.serializers_.ip import IPAddressSerializer
from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from vpn.choices import * from vpn.choices import *
from vpn.models import Tunnel, TunnelGroup, TunnelTermination from vpn.models import Tunnel, TunnelGroup, TunnelTermination
from .crypto import IPSecProfileSerializer from .crypto import IPSecProfileSerializer
@@ -83,9 +81,7 @@ class TunnelTerminationSerializer(NetBoxModelSerializer):
termination_type = ContentTypeField( termination_type = ContentTypeField(
queryset=ContentType.objects.all() queryset=ContentType.objects.all()
) )
termination = serializers.SerializerMethodField( termination = GFKSerializerField(read_only=True)
read_only=True
)
outside_ip = IPAddressSerializer( outside_ip = IPAddressSerializer(
nested=True, nested=True,
required=False, required=False,
@@ -99,11 +95,3 @@ class TunnelTerminationSerializer(NetBoxModelSerializer):
'termination', 'outside_ip', 'tags', 'custom_fields', 'created', 'last_updated', 'termination', 'outside_ip', 'tags', 'custom_fields', 'created', 'last_updated',
) )
brief_fields = ('id', 'url', 'display') brief_fields = ('id', 'url', 'display')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_termination(self, obj):
if not obj.termination:
return None
serializer = get_serializer_for_model(obj.termination)
context = {'request': self.context['request']}
return serializer(obj.termination, nested=True, context=context).data

View File

@@ -1,13 +1,12 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
from dcim.constants import LOCATION_SCOPE_TYPES from dcim.constants import LOCATION_SCOPE_TYPES
from ipam.api.serializers_.vlans import VLANSerializer from ipam.api.serializers_.vlans import VLANSerializer
from netbox.api.fields import ChoiceField, ContentTypeField from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.gfk_fields import GFKSerializerField
from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer
from tenancy.api.serializers_.tenants import TenantSerializer from tenancy.api.serializers_.tenants import TenantSerializer
from utilities.api import get_serializer_for_model
from wireless.choices import * from wireless.choices import *
from wireless.models import WirelessLAN, WirelessLANGroup from wireless.models import WirelessLAN, WirelessLANGroup
from .nested import NestedWirelessLANGroupSerializer from .nested import NestedWirelessLANGroupSerializer
@@ -47,7 +46,7 @@ class WirelessLANSerializer(PrimaryModelSerializer):
default=None default=None
) )
scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
scope = serializers.SerializerMethodField(read_only=True) scope = GFKSerializerField(read_only=True)
class Meta: class Meta:
model = WirelessLAN model = WirelessLAN
@@ -57,11 +56,3 @@ class WirelessLANSerializer(PrimaryModelSerializer):
'tags', 'custom_fields', 'created', 'last_updated', 'tags', 'custom_fields', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'ssid', 'description') brief_fields = ('id', 'url', 'display', 'ssid', 'description')
@extend_schema_field(serializers.JSONField(allow_null=True))
def get_scope(self, obj):
if obj.scope_id is None:
return None
serializer = get_serializer_for_model(obj.scope)
context = {'request': self.context['request']}
return serializer(obj.scope, nested=True, context=context).data