1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Finished merging writable serializers

This commit is contained in:
Jeremy Stretch
2018-04-05 14:12:43 -04:00
parent 7241783249
commit 821fb1e01e
9 changed files with 105 additions and 230 deletions

View File

@ -59,7 +59,7 @@ class CircuitSerializer(CustomFieldModelSerializer):
provider = NestedProviderSerializer() provider = NestedProviderSerializer()
status = ChoiceFieldSerializer(choices=CIRCUIT_STATUS_CHOICES, required=False) status = ChoiceFieldSerializer(choices=CIRCUIT_STATUS_CHOICES, required=False)
type = NestedCircuitTypeSerializer() type = NestedCircuitTypeSerializer()
tenant = NestedTenantSerializer(required=False) tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Circuit model = Circuit
@ -84,7 +84,7 @@ class NestedCircuitSerializer(WritableNestedSerializer):
class CircuitTerminationSerializer(ValidatedModelSerializer): class CircuitTerminationSerializer(ValidatedModelSerializer):
circuit = NestedCircuitSerializer() circuit = NestedCircuitSerializer()
site = NestedSiteSerializer() site = NestedSiteSerializer()
interface = InterfaceSerializer(required=False) interface = InterfaceSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = CircuitTermination model = CircuitTermination

View File

@ -37,7 +37,7 @@ class NestedRegionSerializer(WritableNestedSerializer):
class RegionSerializer(serializers.ModelSerializer): class RegionSerializer(serializers.ModelSerializer):
parent = NestedRegionSerializer(required=False) parent = NestedRegionSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Region model = Region
@ -50,8 +50,8 @@ class RegionSerializer(serializers.ModelSerializer):
class SiteSerializer(CustomFieldModelSerializer): class SiteSerializer(CustomFieldModelSerializer):
status = ChoiceFieldSerializer(choices=SITE_STATUS_CHOICES, required=False) status = ChoiceFieldSerializer(choices=SITE_STATUS_CHOICES, required=False)
region = NestedRegionSerializer(required=False) region = NestedRegionSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False) tenant = NestedTenantSerializer(required=False, allow_null=True)
time_zone = TimeZoneField(required=False) time_zone = TimeZoneField(required=False)
class Meta: class Meta:
@ -117,9 +117,9 @@ class NestedRackRoleSerializer(WritableNestedSerializer):
class RackSerializer(CustomFieldModelSerializer): class RackSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer() site = NestedSiteSerializer()
group = NestedRackGroupSerializer(required=False) group = NestedRackGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False) tenant = NestedTenantSerializer(required=False, allow_null=True)
role = NestedRackRoleSerializer(required=False) role = NestedRackRoleSerializer(required=False, allow_null=True)
type = ChoiceFieldSerializer(choices=RACK_TYPE_CHOICES, required=False) type = ChoiceFieldSerializer(choices=RACK_TYPE_CHOICES, required=False)
width = ChoiceFieldSerializer(choices=RACK_WIDTH_CHOICES, required=False) width = ChoiceFieldSerializer(choices=RACK_WIDTH_CHOICES, required=False)
@ -186,7 +186,7 @@ class RackUnitSerializer(serializers.Serializer):
class RackReservationSerializer(ValidatedModelSerializer): class RackReservationSerializer(ValidatedModelSerializer):
rack = NestedRackSerializer() rack = NestedRackSerializer()
user = NestedUserSerializer() user = NestedUserSerializer()
tenant = NestedTenantSerializer(required=False) tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = RackReservation model = RackReservation
@ -337,7 +337,7 @@ class NestedDeviceRoleSerializer(WritableNestedSerializer):
# #
class PlatformSerializer(ValidatedModelSerializer): class PlatformSerializer(ValidatedModelSerializer):
manufacturer = NestedManufacturerSerializer(required=False) manufacturer = NestedManufacturerSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Platform model = Platform
@ -387,18 +387,18 @@ class DeviceVirtualChassisSerializer(serializers.ModelSerializer):
class DeviceSerializer(CustomFieldModelSerializer): class DeviceSerializer(CustomFieldModelSerializer):
device_type = NestedDeviceTypeSerializer() device_type = NestedDeviceTypeSerializer()
device_role = NestedDeviceRoleSerializer() device_role = NestedDeviceRoleSerializer()
tenant = NestedTenantSerializer(required=False) tenant = NestedTenantSerializer(required=False, allow_null=True)
platform = NestedPlatformSerializer(required=False) platform = NestedPlatformSerializer(required=False, allow_null=True)
site = NestedSiteSerializer() site = NestedSiteSerializer()
rack = NestedRackSerializer(required=False) rack = NestedRackSerializer(required=False, allow_null=True)
face = ChoiceFieldSerializer(choices=RACK_FACE_CHOICES, required=False) face = ChoiceFieldSerializer(choices=RACK_FACE_CHOICES, required=False)
status = ChoiceFieldSerializer(choices=DEVICE_STATUS_CHOICES, required=False) status = ChoiceFieldSerializer(choices=DEVICE_STATUS_CHOICES, required=False)
primary_ip = DeviceIPAddressSerializer(read_only=True) primary_ip = DeviceIPAddressSerializer(read_only=True)
primary_ip4 = DeviceIPAddressSerializer(required=False) primary_ip4 = DeviceIPAddressSerializer(required=False, allow_null=True)
primary_ip6 = DeviceIPAddressSerializer(required=False) primary_ip6 = DeviceIPAddressSerializer(required=False, allow_null=True)
parent_device = serializers.SerializerMethodField() parent_device = serializers.SerializerMethodField()
cluster = NestedClusterSerializer(required=False) cluster = NestedClusterSerializer(required=False, allow_null=True)
virtual_chassis = DeviceVirtualChassisSerializer(required=False) virtual_chassis = DeviceVirtualChassisSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Device model = Device
@ -462,7 +462,7 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer):
class ConsolePortSerializer(ValidatedModelSerializer): class ConsolePortSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
cs_port = NestedConsoleServerPortSerializer(required=False) cs_port = NestedConsoleServerPortSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = ConsolePort model = ConsolePort
@ -497,7 +497,7 @@ class NestedPowerOutletSerializer(WritableNestedSerializer):
class PowerPortSerializer(ValidatedModelSerializer): class PowerPortSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
power_outlet = NestedPowerOutletSerializer(required=False) power_outlet = NestedPowerOutletSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = PowerPort model = PowerPort
@ -547,11 +547,11 @@ class InterfaceVLANSerializer(WritableNestedSerializer):
class InterfaceSerializer(ValidatedModelSerializer): class InterfaceSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
form_factor = ChoiceFieldSerializer(choices=IFACE_FF_CHOICES, required=False) form_factor = ChoiceFieldSerializer(choices=IFACE_FF_CHOICES, required=False)
lag = NestedInterfaceSerializer(required=False) lag = NestedInterfaceSerializer(required=False, allow_null=True)
is_connected = serializers.SerializerMethodField(read_only=True) is_connected = serializers.SerializerMethodField(read_only=True)
interface_connection = serializers.SerializerMethodField(read_only=True) interface_connection = serializers.SerializerMethodField(read_only=True)
circuit_termination = InterfaceCircuitTerminationSerializer(required=False) circuit_termination = InterfaceCircuitTerminationSerializer(read_only=True)
untagged_vlan = InterfaceVLANSerializer(required=False) untagged_vlan = InterfaceVLANSerializer(required=False, allow_null=True)
mode = ChoiceFieldSerializer(choices=IFACE_MODE_CHOICES, required=False) mode = ChoiceFieldSerializer(choices=IFACE_MODE_CHOICES, required=False)
tagged_vlans = InterfaceVLANSerializer(many=True, required=False) tagged_vlans = InterfaceVLANSerializer(many=True, required=False)
@ -603,27 +603,13 @@ class InterfaceSerializer(ValidatedModelSerializer):
return None return None
# class PeerInterfaceSerializer(serializers.ModelSerializer):
# url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
# device = NestedDeviceSerializer()
# form_factor = ChoiceFieldSerializer(choices=IFACE_FF_CHOICES)
# lag = NestedInterfaceSerializer()
#
# class Meta:
# model = Interface
# fields = [
# 'id', 'url', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only',
# 'description',
# ]
# #
# Device bays # Device bays
# #
class DeviceBaySerializer(ValidatedModelSerializer): class DeviceBaySerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
installed_device = NestedDeviceSerializer(required=False) installed_device = NestedDeviceSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = DeviceBay model = DeviceBay

View File

@ -14,7 +14,7 @@ from ipam.constants import (
) )
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
from virtualization.api.serializers import NestedVirtualMachineSerializer from virtualization.api.serializers import NestedVirtualMachineSerializer
@ -23,7 +23,7 @@ from virtualization.api.serializers import NestedVirtualMachineSerializer
# #
class VRFSerializer(CustomFieldModelSerializer): class VRFSerializer(CustomFieldModelSerializer):
tenant = NestedTenantSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = VRF model = VRF
@ -33,7 +33,7 @@ class VRFSerializer(CustomFieldModelSerializer):
] ]
class NestedVRFSerializer(serializers.ModelSerializer): class NestedVRFSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail')
class Meta: class Meta:
@ -41,15 +41,6 @@ class NestedVRFSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'name', 'rd'] fields = ['id', 'url', 'name', 'rd']
class WritableVRFSerializer(CustomFieldModelSerializer):
class Meta:
model = VRF
fields = [
'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_fields', 'created', 'last_updated',
]
# #
# Roles # Roles
# #
@ -61,7 +52,7 @@ class RoleSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug', 'weight'] fields = ['id', 'name', 'slug', 'weight']
class NestedRoleSerializer(serializers.ModelSerializer): class NestedRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail')
class Meta: class Meta:
@ -80,7 +71,7 @@ class RIRSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug', 'is_private'] fields = ['id', 'name', 'slug', 'is_private']
class NestedRIRSerializer(serializers.ModelSerializer): class NestedRIRSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail')
class Meta: class Meta:
@ -100,9 +91,10 @@ class AggregateSerializer(CustomFieldModelSerializer):
fields = [ fields = [
'id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_fields', 'created', 'last_updated', 'id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_fields', 'created', 'last_updated',
] ]
read_only_fields = ['family']
class NestedAggregateSerializer(serializers.ModelSerializer): class NestedAggregateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail')
class Meta(AggregateSerializer.Meta): class Meta(AggregateSerializer.Meta):
@ -110,34 +102,12 @@ class NestedAggregateSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'family', 'prefix'] fields = ['id', 'url', 'family', 'prefix']
class WritableAggregateSerializer(CustomFieldModelSerializer):
class Meta:
model = Aggregate
fields = ['id', 'prefix', 'rir', 'date_added', 'description', 'custom_fields', 'created', 'last_updated']
# #
# VLAN groups # VLAN groups
# #
class VLANGroupSerializer(serializers.ModelSerializer): class VLANGroupSerializer(ValidatedModelSerializer):
site = NestedSiteSerializer() site = NestedSiteSerializer(required=False, allow_null=True)
class Meta:
model = VLANGroup
fields = ['id', 'name', 'slug', 'site']
class NestedVLANGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlangroup-detail')
class Meta:
model = VLANGroup
fields = ['id', 'url', 'name', 'slug']
class WritableVLANGroupSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = VLANGroup model = VLANGroup
@ -154,21 +124,29 @@ class WritableVLANGroupSerializer(serializers.ModelSerializer):
validator(data) validator(data)
# Enforce model validation # Enforce model validation
super(WritableVLANGroupSerializer, self).validate(data) super(VLANGroupSerializer, self).validate(data)
return data return data
class NestedVLANGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlangroup-detail')
class Meta:
model = VLANGroup
fields = ['id', 'url', 'name', 'slug']
# #
# VLANs # VLANs
# #
class VLANSerializer(CustomFieldModelSerializer): class VLANSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer() site = NestedSiteSerializer(required=False, allow_null=True)
group = NestedVLANGroupSerializer() group = NestedVLANGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=VLAN_STATUS_CHOICES) status = ChoiceFieldSerializer(choices=VLAN_STATUS_CHOICES, required=False)
role = NestedRoleSerializer() role = NestedRoleSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = VLAN model = VLAN
@ -176,24 +154,6 @@ class VLANSerializer(CustomFieldModelSerializer):
'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name', 'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name',
'custom_fields', 'created', 'last_updated', 'custom_fields', 'created', 'last_updated',
] ]
class NestedVLANSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
class Meta:
model = VLAN
fields = ['id', 'url', 'vid', 'name', 'display_name']
class WritableVLANSerializer(CustomFieldModelSerializer):
class Meta:
model = VLAN
fields = [
'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'custom_fields', 'created',
'last_updated',
]
validators = [] validators = []
def validate(self, data): def validate(self, data):
@ -206,22 +166,30 @@ class WritableVLANSerializer(CustomFieldModelSerializer):
validator(data) validator(data)
# Enforce model validation # Enforce model validation
super(WritableVLANSerializer, self).validate(data) super(VLANSerializer, self).validate(data)
return data return data
class NestedVLANSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
class Meta:
model = VLAN
fields = ['id', 'url', 'vid', 'name', 'display_name']
# #
# Prefixes # Prefixes
# #
class PrefixSerializer(CustomFieldModelSerializer): class PrefixSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer() site = NestedSiteSerializer(required=False, allow_null=True)
vrf = NestedVRFSerializer() vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True)
vlan = NestedVLANSerializer() vlan = NestedVLANSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=PREFIX_STATUS_CHOICES) status = ChoiceFieldSerializer(choices=PREFIX_STATUS_CHOICES, required=False)
role = NestedRoleSerializer() role = NestedRoleSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Prefix model = Prefix
@ -229,9 +197,10 @@ class PrefixSerializer(CustomFieldModelSerializer):
'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description', 'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
'custom_fields', 'created', 'last_updated', 'custom_fields', 'created', 'last_updated',
] ]
read_only_fields = ['family']
class NestedPrefixSerializer(serializers.ModelSerializer): class NestedPrefixSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:prefix-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:prefix-detail')
class Meta: class Meta:
@ -239,16 +208,6 @@ class NestedPrefixSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'family', 'prefix'] fields = ['id', 'url', 'family', 'prefix']
class WritablePrefixSerializer(CustomFieldModelSerializer):
class Meta:
model = Prefix
fields = [
'id', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
'custom_fields', 'created', 'last_updated',
]
class AvailablePrefixSerializer(serializers.Serializer): class AvailablePrefixSerializer(serializers.Serializer):
def to_representation(self, instance): def to_representation(self, instance):
@ -288,11 +247,11 @@ class IPAddressInterfaceSerializer(serializers.ModelSerializer):
class IPAddressSerializer(CustomFieldModelSerializer): class IPAddressSerializer(CustomFieldModelSerializer):
vrf = NestedVRFSerializer() vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=IPADDRESS_STATUS_CHOICES) status = ChoiceFieldSerializer(choices=IPADDRESS_STATUS_CHOICES, required=False)
role = ChoiceFieldSerializer(choices=IPADDRESS_ROLE_CHOICES) role = ChoiceFieldSerializer(choices=IPADDRESS_ROLE_CHOICES, required=False)
interface = IPAddressInterfaceSerializer() interface = IPAddressInterfaceSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = IPAddress model = IPAddress
@ -300,9 +259,10 @@ class IPAddressSerializer(CustomFieldModelSerializer):
'id', 'family', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'description', 'nat_inside', 'id', 'family', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'description', 'nat_inside',
'nat_outside', 'custom_fields', 'created', 'last_updated', 'nat_outside', 'custom_fields', 'created', 'last_updated',
] ]
read_only_fields = ['family']
class NestedIPAddressSerializer(serializers.ModelSerializer): class NestedIPAddressSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
class Meta: class Meta:
@ -310,18 +270,8 @@ class NestedIPAddressSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'family', 'address'] fields = ['id', 'url', 'family', 'address']
IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer() IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer(required=False, allow_null=True)
IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer() IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer(read_only=True)
class WritableIPAddressSerializer(CustomFieldModelSerializer):
class Meta:
model = IPAddress
fields = [
'id', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'description', 'nat_inside',
'custom_fields', 'created', 'last_updated',
]
class AvailableIPSerializer(serializers.Serializer): class AvailableIPSerializer(serializers.Serializer):
@ -342,22 +292,11 @@ class AvailableIPSerializer(serializers.Serializer):
# Services # Services
# #
class ServiceSerializer(serializers.ModelSerializer): class ServiceSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer(required=False, allow_null=True)
virtual_machine = NestedVirtualMachineSerializer() virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
protocol = ChoiceFieldSerializer(choices=IP_PROTOCOL_CHOICES) protocol = ChoiceFieldSerializer(choices=IP_PROTOCOL_CHOICES)
ipaddresses = NestedIPAddressSerializer(many=True) ipaddresses = NestedIPAddressSerializer(many=True, required=False)
class Meta:
model = Service
fields = [
'id', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description', 'created',
'last_updated',
]
# TODO: Figure out how to use model validation with ManyToManyFields. Calling clean() yields a ValueError.
class WritableServiceSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Service model = Service

View File

@ -35,7 +35,6 @@ class IPAMFieldChoicesViewSet(FieldChoicesViewSet):
class VRFViewSet(CustomFieldModelViewSet): class VRFViewSet(CustomFieldModelViewSet):
queryset = VRF.objects.select_related('tenant') queryset = VRF.objects.select_related('tenant')
serializer_class = serializers.VRFSerializer serializer_class = serializers.VRFSerializer
write_serializer_class = serializers.WritableVRFSerializer
filter_class = filters.VRFFilter filter_class = filters.VRFFilter
@ -56,7 +55,6 @@ class RIRViewSet(ModelViewSet):
class AggregateViewSet(CustomFieldModelViewSet): class AggregateViewSet(CustomFieldModelViewSet):
queryset = Aggregate.objects.select_related('rir') queryset = Aggregate.objects.select_related('rir')
serializer_class = serializers.AggregateSerializer serializer_class = serializers.AggregateSerializer
write_serializer_class = serializers.WritableAggregateSerializer
filter_class = filters.AggregateFilter filter_class = filters.AggregateFilter
@ -77,7 +75,6 @@ class RoleViewSet(ModelViewSet):
class PrefixViewSet(CustomFieldModelViewSet): class PrefixViewSet(CustomFieldModelViewSet):
queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role') queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
serializer_class = serializers.PrefixSerializer serializer_class = serializers.PrefixSerializer
write_serializer_class = serializers.WritablePrefixSerializer
filter_class = filters.PrefixFilter filter_class = filters.PrefixFilter
@detail_route(url_path='available-prefixes', methods=['get', 'post']) @detail_route(url_path='available-prefixes', methods=['get', 'post'])
@ -120,9 +117,9 @@ class PrefixViewSet(CustomFieldModelViewSet):
# Initialize the serializer with a list or a single object depending on what was requested # Initialize the serializer with a list or a single object depending on what was requested
if isinstance(request.data, list): if isinstance(request.data, list):
serializer = serializers.WritablePrefixSerializer(data=requested_prefixes, many=True) serializer = serializers.PrefixSerializer(data=requested_prefixes, many=True)
else: else:
serializer = serializers.WritablePrefixSerializer(data=requested_prefixes[0]) serializer = serializers.PrefixSerializer(data=requested_prefixes[0])
# Create the new Prefix(es) # Create the new Prefix(es)
if serializer.is_valid(): if serializer.is_valid():
@ -177,9 +174,9 @@ class PrefixViewSet(CustomFieldModelViewSet):
# Initialize the serializer with a list or a single object depending on what was requested # Initialize the serializer with a list or a single object depending on what was requested
if isinstance(request.data, list): if isinstance(request.data, list):
serializer = serializers.WritableIPAddressSerializer(data=requested_ips, many=True) serializer = serializers.IPAddressSerializer(data=requested_ips, many=True)
else: else:
serializer = serializers.WritableIPAddressSerializer(data=requested_ips[0]) serializer = serializers.IPAddressSerializer(data=requested_ips[0])
# Create the new IP address(es) # Create the new IP address(es)
if serializer.is_valid(): if serializer.is_valid():
@ -223,7 +220,6 @@ class IPAddressViewSet(CustomFieldModelViewSet):
'nat_outside' 'nat_outside'
) )
serializer_class = serializers.IPAddressSerializer serializer_class = serializers.IPAddressSerializer
write_serializer_class = serializers.WritableIPAddressSerializer
filter_class = filters.IPAddressFilter filter_class = filters.IPAddressFilter
@ -234,7 +230,6 @@ class IPAddressViewSet(CustomFieldModelViewSet):
class VLANGroupViewSet(ModelViewSet): class VLANGroupViewSet(ModelViewSet):
queryset = VLANGroup.objects.select_related('site') queryset = VLANGroup.objects.select_related('site')
serializer_class = serializers.VLANGroupSerializer serializer_class = serializers.VLANGroupSerializer
write_serializer_class = serializers.WritableVLANGroupSerializer
filter_class = filters.VLANGroupFilter filter_class = filters.VLANGroupFilter
@ -245,7 +240,6 @@ class VLANGroupViewSet(ModelViewSet):
class VLANViewSet(CustomFieldModelViewSet): class VLANViewSet(CustomFieldModelViewSet):
queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role') queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role')
serializer_class = serializers.VLANSerializer serializer_class = serializers.VLANSerializer
write_serializer_class = serializers.WritableVLANSerializer
filter_class = filters.VLANFilter filter_class = filters.VLANFilter
@ -256,5 +250,4 @@ class VLANViewSet(CustomFieldModelViewSet):
class ServiceViewSet(ModelViewSet): class ServiceViewSet(ModelViewSet):
queryset = Service.objects.select_related('device') queryset = Service.objects.select_related('device')
serializer_class = serializers.ServiceSerializer serializer_class = serializers.ServiceSerializer
write_serializer_class = serializers.WritableServiceSerializer
filter_class = filters.ServiceFilter filter_class = filters.ServiceFilter

View File

@ -5,7 +5,7 @@ from rest_framework.validators import UniqueTogetherValidator
from dcim.api.serializers import NestedDeviceSerializer from dcim.api.serializers import NestedDeviceSerializer
from secrets.models import Secret, SecretRole from secrets.models import Secret, SecretRole
from utilities.api import ValidatedModelSerializer from utilities.api import ValidatedModelSerializer, WritableNestedSerializer
# #
@ -19,7 +19,7 @@ class SecretRoleSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug'] fields = ['id', 'name', 'slug']
class NestedSecretRoleSerializer(serializers.ModelSerializer): class NestedSecretRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='secrets-api:secretrole-detail') url = serializers.HyperlinkedIdentityField(view_name='secrets-api:secretrole-detail')
class Meta: class Meta:
@ -31,16 +31,9 @@ class NestedSecretRoleSerializer(serializers.ModelSerializer):
# Secrets # Secrets
# #
class SecretSerializer(serializers.ModelSerializer): class SecretSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
role = NestedSecretRoleSerializer() role = NestedSecretRoleSerializer()
class Meta:
model = Secret
fields = ['id', 'device', 'role', 'name', 'plaintext', 'hash', 'created', 'last_updated']
class WritableSecretSerializer(serializers.ModelSerializer):
plaintext = serializers.CharField() plaintext = serializers.CharField()
class Meta: class Meta:
@ -64,6 +57,6 @@ class WritableSecretSerializer(serializers.ModelSerializer):
validator(data) validator(data)
# Enforce model validation # Enforce model validation
super(WritableSecretSerializer, self).validate(data) super(SecretSerializer, self).validate(data)
return data return data

View File

@ -51,7 +51,6 @@ class SecretViewSet(ModelViewSet):
'role__users', 'role__groups', 'role__users', 'role__groups',
) )
serializer_class = serializers.SecretSerializer serializer_class = serializers.SecretSerializer
write_serializer_class = serializers.WritableSecretSerializer
filter_class = filters.SecretFilter filter_class = filters.SecretFilter
master_key = None master_key = None

View File

@ -131,6 +131,8 @@ class WritableNestedSerializer(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.
""" """
def to_internal_value(self, data): def to_internal_value(self, data):
if data is None:
return None
try: try:
return self.Meta.model.objects.get(pk=data) return self.Meta.model.objects.get(pk=data)
except ObjectDoesNotExist: except ObjectDoesNotExist:
@ -148,16 +150,8 @@ class ModelViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin, mixins.ListModelMixin,
GenericViewSet): GenericViewSet):
""" """
Substitute DRF's built-in ModelViewSet for our own, which introduces a bit of additional functionality: Accept either a single object or a list of objects to create.
1. Use an alternate serializer (if provided) for write operations
2. Accept either a single object or a list of objects to create
""" """
def get_serializer_class(self):
# Check for a different serializer to use for write operations
if self.action in WRITE_OPERATIONS and hasattr(self, 'write_serializer_class'):
return self.write_serializer_class
return self.serializer_class
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
# If a list of objects has been provided, initialize the serializer with many=True # If a list of objects has been provided, initialize the serializer with many=True
if isinstance(kwargs.get('data', {}), list): if isinstance(kwargs.get('data', {}), list):

View File

@ -8,7 +8,7 @@ from dcim.models import Interface
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from ipam.models import IPAddress from ipam.models import IPAddress
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
from virtualization.constants import VM_STATUS_CHOICES from virtualization.constants import VM_STATUS_CHOICES
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -24,7 +24,7 @@ class ClusterTypeSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug'] fields = ['id', 'name', 'slug']
class NestedClusterTypeSerializer(serializers.ModelSerializer): class NestedClusterTypeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail') url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail')
class Meta: class Meta:
@ -43,7 +43,7 @@ class ClusterGroupSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug'] fields = ['id', 'name', 'slug']
class NestedClusterGroupSerializer(serializers.ModelSerializer): class NestedClusterGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail') url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail')
class Meta: class Meta:
@ -57,15 +57,15 @@ class NestedClusterGroupSerializer(serializers.ModelSerializer):
class ClusterSerializer(CustomFieldModelSerializer): class ClusterSerializer(CustomFieldModelSerializer):
type = NestedClusterTypeSerializer() type = NestedClusterTypeSerializer()
group = NestedClusterGroupSerializer() group = NestedClusterGroupSerializer(required=False, allow_null=True)
site = NestedSiteSerializer() site = NestedSiteSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = Cluster model = Cluster
fields = ['id', 'name', 'type', 'group', 'site', 'comments', 'custom_fields', 'created', 'last_updated'] fields = ['id', 'name', 'type', 'group', 'site', 'comments', 'custom_fields', 'created', 'last_updated']
class NestedClusterSerializer(serializers.ModelSerializer): class NestedClusterSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:cluster-detail') url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:cluster-detail')
class Meta: class Meta:
@ -73,13 +73,6 @@ class NestedClusterSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'name'] fields = ['id', 'url', 'name']
class WritableClusterSerializer(CustomFieldModelSerializer):
class Meta:
model = Cluster
fields = ['id', 'name', 'type', 'group', 'site', 'comments', 'custom_fields', 'created', 'last_updated']
# #
# Virtual machines # Virtual machines
# #
@ -94,14 +87,14 @@ class VirtualMachineIPAddressSerializer(serializers.ModelSerializer):
class VirtualMachineSerializer(CustomFieldModelSerializer): class VirtualMachineSerializer(CustomFieldModelSerializer):
status = ChoiceFieldSerializer(choices=VM_STATUS_CHOICES) status = ChoiceFieldSerializer(choices=VM_STATUS_CHOICES, required=False)
cluster = NestedClusterSerializer() cluster = NestedClusterSerializer(required=False, allow_null=True)
role = NestedDeviceRoleSerializer() role = NestedDeviceRoleSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True)
platform = NestedPlatformSerializer() platform = NestedPlatformSerializer(required=False, allow_null=True)
primary_ip = VirtualMachineIPAddressSerializer() primary_ip = VirtualMachineIPAddressSerializer(read_only=True)
primary_ip4 = VirtualMachineIPAddressSerializer() primary_ip4 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
primary_ip6 = VirtualMachineIPAddressSerializer() primary_ip6 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
class Meta: class Meta:
model = VirtualMachine model = VirtualMachine
@ -111,7 +104,7 @@ class VirtualMachineSerializer(CustomFieldModelSerializer):
] ]
class NestedVirtualMachineSerializer(serializers.ModelSerializer): class NestedVirtualMachineSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:virtualmachine-detail') url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:virtualmachine-detail')
class Meta: class Meta:
@ -119,22 +112,13 @@ class NestedVirtualMachineSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'name'] fields = ['id', 'url', 'name']
class WritableVirtualMachineSerializer(CustomFieldModelSerializer):
class Meta:
model = VirtualMachine
fields = [
'id', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'vcpus',
'memory', 'disk', 'comments', 'custom_fields', 'created', 'last_updated',
]
# #
# VM interfaces # VM interfaces
# #
class InterfaceSerializer(serializers.ModelSerializer): class InterfaceSerializer(ValidatedModelSerializer):
virtual_machine = NestedVirtualMachineSerializer() virtual_machine = NestedVirtualMachineSerializer()
form_factor = serializers.IntegerField(default=IFACE_FF_VIRTUAL)
class Meta: class Meta:
model = Interface model = Interface
@ -143,19 +127,9 @@ class InterfaceSerializer(serializers.ModelSerializer):
] ]
class NestedInterfaceSerializer(serializers.ModelSerializer): class NestedInterfaceSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:interface-detail') url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:interface-detail')
class Meta: class Meta:
model = Interface model = Interface
fields = ['id', 'url', 'name'] fields = ['id', 'url', 'name']
class WritableInterfaceSerializer(ValidatedModelSerializer):
form_factor = serializers.IntegerField(default=IFACE_FF_VIRTUAL)
class Meta:
model = Interface
fields = [
'id', 'name', 'virtual_machine', 'form_factor', 'enabled', 'mac_address', 'mtu', 'description',
]

View File

@ -37,7 +37,6 @@ class ClusterGroupViewSet(ModelViewSet):
class ClusterViewSet(CustomFieldModelViewSet): class ClusterViewSet(CustomFieldModelViewSet):
queryset = Cluster.objects.select_related('type', 'group') queryset = Cluster.objects.select_related('type', 'group')
serializer_class = serializers.ClusterSerializer serializer_class = serializers.ClusterSerializer
write_serializer_class = serializers.WritableClusterSerializer
filter_class = filters.ClusterFilter filter_class = filters.ClusterFilter
@ -48,12 +47,10 @@ class ClusterViewSet(CustomFieldModelViewSet):
class VirtualMachineViewSet(CustomFieldModelViewSet): class VirtualMachineViewSet(CustomFieldModelViewSet):
queryset = VirtualMachine.objects.all() queryset = VirtualMachine.objects.all()
serializer_class = serializers.VirtualMachineSerializer serializer_class = serializers.VirtualMachineSerializer
write_serializer_class = serializers.WritableVirtualMachineSerializer
filter_class = filters.VirtualMachineFilter filter_class = filters.VirtualMachineFilter
class InterfaceViewSet(ModelViewSet): class InterfaceViewSet(ModelViewSet):
queryset = Interface.objects.filter(virtual_machine__isnull=False).select_related('virtual_machine') queryset = Interface.objects.filter(virtual_machine__isnull=False).select_related('virtual_machine')
serializer_class = serializers.InterfaceSerializer serializer_class = serializers.InterfaceSerializer
write_serializer_class = serializers.WritableInterfaceSerializer
filter_class = filters.InterfaceFilter filter_class = filters.InterfaceFilter