mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Introduce NestedGroupModelSerializer
This commit is contained in:
@ -4,7 +4,7 @@ from circuits.choices import CircuitStatusChoices
|
|||||||
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
|
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
|
||||||
from dcim.api.nested_serializers import NestedCableSerializer, NestedSiteSerializer
|
from dcim.api.nested_serializers import NestedCableSerializer, NestedSiteSerializer
|
||||||
from dcim.api.serializers import CableTerminationSerializer, ConnectedEndpointSerializer
|
from dcim.api.serializers import CableTerminationSerializer, ConnectedEndpointSerializer
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from netbox.api import ChoiceField
|
from netbox.api import ChoiceField
|
||||||
from netbox.api.serializers import OrganizationalModelSerializer, WritableNestedSerializer
|
from netbox.api.serializers import OrganizationalModelSerializer, WritableNestedSerializer
|
||||||
|
@ -13,12 +13,14 @@ from dcim.models import (
|
|||||||
PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
|
PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
|
||||||
VirtualChassis,
|
VirtualChassis,
|
||||||
)
|
)
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
|
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
|
||||||
from ipam.models import VLAN
|
from ipam.models import VLAN
|
||||||
from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField, TimeZoneField
|
from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField, TimeZoneField
|
||||||
from netbox.api.serializers import OrganizationalModelSerializer, ValidatedModelSerializer, WritableNestedSerializer
|
from netbox.api.serializers import (
|
||||||
|
NestedGroupModelSerializer, OrganizationalModelSerializer, ValidatedModelSerializer, WritableNestedSerializer,
|
||||||
|
)
|
||||||
from tenancy.api.nested_serializers import NestedTenantSerializer
|
from tenancy.api.nested_serializers import NestedTenantSerializer
|
||||||
from users.api.nested_serializers import NestedUserSerializer
|
from users.api.nested_serializers import NestedUserSerializer
|
||||||
from utilities.api import get_serializer_for_model
|
from utilities.api import get_serializer_for_model
|
||||||
@ -79,11 +81,10 @@ class ConnectedEndpointSerializer(ValidatedModelSerializer):
|
|||||||
# Regions/sites
|
# Regions/sites
|
||||||
#
|
#
|
||||||
|
|
||||||
class RegionSerializer(CustomFieldModelSerializer):
|
class RegionSerializer(NestedGroupModelSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:region-detail')
|
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:region-detail')
|
||||||
parent = NestedRegionSerializer(required=False, allow_null=True)
|
parent = NestedRegionSerializer(required=False, allow_null=True)
|
||||||
site_count = serializers.IntegerField(read_only=True)
|
site_count = serializers.IntegerField(read_only=True)
|
||||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Region
|
model = Region
|
||||||
@ -120,12 +121,11 @@ class SiteSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
|
|||||||
# Racks
|
# Racks
|
||||||
#
|
#
|
||||||
|
|
||||||
class RackGroupSerializer(CustomFieldModelSerializer):
|
class RackGroupSerializer(NestedGroupModelSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackgroup-detail')
|
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackgroup-detail')
|
||||||
site = NestedSiteSerializer()
|
site = NestedSiteSerializer()
|
||||||
parent = NestedRackGroupSerializer(required=False, allow_null=True)
|
parent = NestedRackGroupSerializer(required=False, allow_null=True)
|
||||||
rack_count = serializers.IntegerField(read_only=True)
|
rack_count = serializers.IntegerField(read_only=True)
|
||||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RackGroup
|
model = RackGroup
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from rest_framework.fields import CreateOnlyDefault, Field
|
from rest_framework.fields import Field
|
||||||
|
|
||||||
from extras.choices import *
|
|
||||||
from extras.models import CustomField
|
from extras.models import CustomField
|
||||||
from netbox.api import ValidatedModelSerializer
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -56,34 +54,3 @@ class CustomFieldsDataField(Field):
|
|||||||
data = {**self.parent.instance.custom_field_data, **data}
|
data = {**self.parent.instance.custom_field_data, **data}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldModelSerializer(ValidatedModelSerializer):
|
|
||||||
"""
|
|
||||||
Extends ModelSerializer to render any CustomFields and their values associated with an object.
|
|
||||||
"""
|
|
||||||
custom_fields = CustomFieldsDataField(
|
|
||||||
source='custom_field_data',
|
|
||||||
default=CreateOnlyDefault(CustomFieldDefaultValues())
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
if self.instance is not None:
|
|
||||||
|
|
||||||
# Retrieve the set of CustomFields which apply to this type of object
|
|
||||||
content_type = ContentType.objects.get_for_model(self.Meta.model)
|
|
||||||
fields = CustomField.objects.filter(content_types=content_type)
|
|
||||||
|
|
||||||
# Populate CustomFieldValues for each instance from database
|
|
||||||
if type(self.instance) in (list, tuple):
|
|
||||||
for obj in self.instance:
|
|
||||||
self._populate_custom_fields(obj, fields)
|
|
||||||
else:
|
|
||||||
self._populate_custom_fields(self.instance, fields)
|
|
||||||
|
|
||||||
def _populate_custom_fields(self, instance, custom_fields):
|
|
||||||
instance.custom_fields = {}
|
|
||||||
for field in custom_fields:
|
|
||||||
instance.custom_fields[field.name] = instance.cf.get(field.name)
|
|
||||||
|
@ -6,7 +6,7 @@ from rest_framework import serializers
|
|||||||
from rest_framework.validators import UniqueTogetherValidator
|
from rest_framework.validators import UniqueTogetherValidator
|
||||||
|
|
||||||
from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
|
from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from ipam.choices import *
|
from ipam.choices import *
|
||||||
from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
|
from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist
|
from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist
|
||||||
from django.db.models import ManyToManyField
|
from django.db.models import ManyToManyField
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
from rest_framework.fields import CreateOnlyDefault
|
||||||
|
|
||||||
|
from extras.api.customfields import CustomFieldsDataField, CustomFieldDefaultValues
|
||||||
|
from extras.models import CustomField
|
||||||
from utilities.utils import dict_to_filter_params
|
from utilities.utils import dict_to_filter_params
|
||||||
|
|
||||||
|
|
||||||
@ -35,10 +39,45 @@ class ValidatedModelSerializer(serializers.ModelSerializer):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class OrganizationalModelSerializer(ValidatedModelSerializer):
|
class CustomFieldModelSerializer(ValidatedModelSerializer):
|
||||||
|
"""
|
||||||
|
Extends ModelSerializer to render any CustomFields and their values associated with an object.
|
||||||
|
"""
|
||||||
|
custom_fields = CustomFieldsDataField(
|
||||||
|
source='custom_field_data',
|
||||||
|
default=CreateOnlyDefault(CustomFieldDefaultValues())
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
if self.instance is not None:
|
||||||
|
|
||||||
|
# Retrieve the set of CustomFields which apply to this type of object
|
||||||
|
content_type = ContentType.objects.get_for_model(self.Meta.model)
|
||||||
|
fields = CustomField.objects.filter(content_types=content_type)
|
||||||
|
|
||||||
|
# Populate CustomFieldValues for each instance from database
|
||||||
|
if type(self.instance) in (list, tuple):
|
||||||
|
for obj in self.instance:
|
||||||
|
self._populate_custom_fields(obj, fields)
|
||||||
|
else:
|
||||||
|
self._populate_custom_fields(self.instance, fields)
|
||||||
|
|
||||||
|
def _populate_custom_fields(self, instance, custom_fields):
|
||||||
|
instance.custom_fields = {}
|
||||||
|
for field in custom_fields:
|
||||||
|
instance.custom_fields[field.name] = instance.cf.get(field.name)
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationalModelSerializer(CustomFieldModelSerializer):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NestedGroupModelSerializer(CustomFieldModelSerializer):
|
||||||
|
_depth = serializers.IntegerField(source='level', read_only=True)
|
||||||
|
|
||||||
|
|
||||||
class WritableNestedSerializer(serializers.ModelSerializer):
|
class WritableNestedSerializer(serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
Returns a nested representation of an object on read, but accepts only a primary key on write.
|
Returns a nested representation of an object on read, but accepts only a primary key on write.
|
||||||
|
@ -2,7 +2,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||||||
from drf_yasg.utils import swagger_serializer_method
|
from drf_yasg.utils import swagger_serializer_method
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from secrets.constants import SECRET_ASSIGNMENT_MODELS
|
from secrets.constants import SECRET_ASSIGNMENT_MODELS
|
||||||
from secrets.models import Secret, SecretRole
|
from secrets.models import Secret, SecretRole
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer, NestedGroupModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from netbox.api import ValidatedModelSerializer
|
|
||||||
from tenancy.models import Tenant, TenantGroup
|
from tenancy.models import Tenant, TenantGroup
|
||||||
from .nested_serializers import *
|
from .nested_serializers import *
|
||||||
|
|
||||||
@ -11,11 +10,10 @@ from .nested_serializers import *
|
|||||||
# Tenants
|
# Tenants
|
||||||
#
|
#
|
||||||
|
|
||||||
class TenantGroupSerializer(CustomFieldModelSerializer):
|
class TenantGroupSerializer(NestedGroupModelSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenantgroup-detail')
|
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenantgroup-detail')
|
||||||
parent = NestedTenantGroupSerializer(required=False, allow_null=True)
|
parent = NestedTenantGroupSerializer(required=False, allow_null=True)
|
||||||
tenant_count = serializers.IntegerField(read_only=True)
|
tenant_count = serializers.IntegerField(read_only=True)
|
||||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TenantGroup
|
model = TenantGroup
|
||||||
|
@ -3,7 +3,7 @@ from rest_framework import serializers
|
|||||||
|
|
||||||
from dcim.api.nested_serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
|
from dcim.api.nested_serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
|
||||||
from dcim.choices import InterfaceModeChoices
|
from dcim.choices import InterfaceModeChoices
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from netbox.api.serializers import CustomFieldModelSerializer
|
||||||
from extras.api.serializers import TaggedObjectSerializer
|
from extras.api.serializers import TaggedObjectSerializer
|
||||||
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
|
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
|
||||||
from ipam.models import VLAN
|
from ipam.models import VLAN
|
||||||
|
Reference in New Issue
Block a user