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()
status = ChoiceFieldSerializer(choices=CIRCUIT_STATUS_CHOICES, required=False)
type = NestedCircuitTypeSerializer()
tenant = NestedTenantSerializer(required=False)
tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta:
model = Circuit
@ -84,7 +84,7 @@ class NestedCircuitSerializer(WritableNestedSerializer):
class CircuitTerminationSerializer(ValidatedModelSerializer):
circuit = NestedCircuitSerializer()
site = NestedSiteSerializer()
interface = InterfaceSerializer(required=False)
interface = InterfaceSerializer(required=False, allow_null=True)
class Meta:
model = CircuitTermination

View File

@ -37,7 +37,7 @@ class NestedRegionSerializer(WritableNestedSerializer):
class RegionSerializer(serializers.ModelSerializer):
parent = NestedRegionSerializer(required=False)
parent = NestedRegionSerializer(required=False, allow_null=True)
class Meta:
model = Region
@ -50,8 +50,8 @@ class RegionSerializer(serializers.ModelSerializer):
class SiteSerializer(CustomFieldModelSerializer):
status = ChoiceFieldSerializer(choices=SITE_STATUS_CHOICES, required=False)
region = NestedRegionSerializer(required=False)
tenant = NestedTenantSerializer(required=False)
region = NestedRegionSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
time_zone = TimeZoneField(required=False)
class Meta:
@ -117,9 +117,9 @@ class NestedRackRoleSerializer(WritableNestedSerializer):
class RackSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer()
group = NestedRackGroupSerializer(required=False)
tenant = NestedTenantSerializer(required=False)
role = NestedRackRoleSerializer(required=False)
group = NestedRackGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
role = NestedRackRoleSerializer(required=False, allow_null=True)
type = ChoiceFieldSerializer(choices=RACK_TYPE_CHOICES, required=False)
width = ChoiceFieldSerializer(choices=RACK_WIDTH_CHOICES, required=False)
@ -186,7 +186,7 @@ class RackUnitSerializer(serializers.Serializer):
class RackReservationSerializer(ValidatedModelSerializer):
rack = NestedRackSerializer()
user = NestedUserSerializer()
tenant = NestedTenantSerializer(required=False)
tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta:
model = RackReservation
@ -337,7 +337,7 @@ class NestedDeviceRoleSerializer(WritableNestedSerializer):
#
class PlatformSerializer(ValidatedModelSerializer):
manufacturer = NestedManufacturerSerializer(required=False)
manufacturer = NestedManufacturerSerializer(required=False, allow_null=True)
class Meta:
model = Platform
@ -387,18 +387,18 @@ class DeviceVirtualChassisSerializer(serializers.ModelSerializer):
class DeviceSerializer(CustomFieldModelSerializer):
device_type = NestedDeviceTypeSerializer()
device_role = NestedDeviceRoleSerializer()
tenant = NestedTenantSerializer(required=False)
platform = NestedPlatformSerializer(required=False)
tenant = NestedTenantSerializer(required=False, allow_null=True)
platform = NestedPlatformSerializer(required=False, allow_null=True)
site = NestedSiteSerializer()
rack = NestedRackSerializer(required=False)
rack = NestedRackSerializer(required=False, allow_null=True)
face = ChoiceFieldSerializer(choices=RACK_FACE_CHOICES, required=False)
status = ChoiceFieldSerializer(choices=DEVICE_STATUS_CHOICES, required=False)
primary_ip = DeviceIPAddressSerializer(read_only=True)
primary_ip4 = DeviceIPAddressSerializer(required=False)
primary_ip6 = DeviceIPAddressSerializer(required=False)
primary_ip4 = DeviceIPAddressSerializer(required=False, allow_null=True)
primary_ip6 = DeviceIPAddressSerializer(required=False, allow_null=True)
parent_device = serializers.SerializerMethodField()
cluster = NestedClusterSerializer(required=False)
virtual_chassis = DeviceVirtualChassisSerializer(required=False)
cluster = NestedClusterSerializer(required=False, allow_null=True)
virtual_chassis = DeviceVirtualChassisSerializer(required=False, allow_null=True)
class Meta:
model = Device
@ -462,7 +462,7 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer):
class ConsolePortSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer()
cs_port = NestedConsoleServerPortSerializer(required=False)
cs_port = NestedConsoleServerPortSerializer(required=False, allow_null=True)
class Meta:
model = ConsolePort
@ -497,7 +497,7 @@ class NestedPowerOutletSerializer(WritableNestedSerializer):
class PowerPortSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer()
power_outlet = NestedPowerOutletSerializer(required=False)
power_outlet = NestedPowerOutletSerializer(required=False, allow_null=True)
class Meta:
model = PowerPort
@ -547,11 +547,11 @@ class InterfaceVLANSerializer(WritableNestedSerializer):
class InterfaceSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer()
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)
interface_connection = serializers.SerializerMethodField(read_only=True)
circuit_termination = InterfaceCircuitTerminationSerializer(required=False)
untagged_vlan = InterfaceVLANSerializer(required=False)
circuit_termination = InterfaceCircuitTerminationSerializer(read_only=True)
untagged_vlan = InterfaceVLANSerializer(required=False, allow_null=True)
mode = ChoiceFieldSerializer(choices=IFACE_MODE_CHOICES, required=False)
tagged_vlans = InterfaceVLANSerializer(many=True, required=False)
@ -603,27 +603,13 @@ class InterfaceSerializer(ValidatedModelSerializer):
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
#
class DeviceBaySerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer()
installed_device = NestedDeviceSerializer(required=False)
installed_device = NestedDeviceSerializer(required=False, allow_null=True)
class Meta:
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 tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
from virtualization.api.serializers import NestedVirtualMachineSerializer
@ -23,7 +23,7 @@ from virtualization.api.serializers import NestedVirtualMachineSerializer
#
class VRFSerializer(CustomFieldModelSerializer):
tenant = NestedTenantSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True)
class Meta:
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')
class Meta:
@ -41,15 +41,6 @@ class NestedVRFSerializer(serializers.ModelSerializer):
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
#
@ -61,7 +52,7 @@ class RoleSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug', 'weight']
class NestedRoleSerializer(serializers.ModelSerializer):
class NestedRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail')
class Meta:
@ -80,7 +71,7 @@ class RIRSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug', 'is_private']
class NestedRIRSerializer(serializers.ModelSerializer):
class NestedRIRSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail')
class Meta:
@ -100,9 +91,10 @@ class AggregateSerializer(CustomFieldModelSerializer):
fields = [
'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')
class Meta(AggregateSerializer.Meta):
@ -110,34 +102,12 @@ class NestedAggregateSerializer(serializers.ModelSerializer):
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
#
class VLANGroupSerializer(serializers.ModelSerializer):
site = NestedSiteSerializer()
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 VLANGroupSerializer(ValidatedModelSerializer):
site = NestedSiteSerializer(required=False, allow_null=True)
class Meta:
model = VLANGroup
@ -154,21 +124,29 @@ class WritableVLANGroupSerializer(serializers.ModelSerializer):
validator(data)
# Enforce model validation
super(WritableVLANGroupSerializer, self).validate(data)
super(VLANGroupSerializer, self).validate(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
#
class VLANSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer()
group = NestedVLANGroupSerializer()
tenant = NestedTenantSerializer()
status = ChoiceFieldSerializer(choices=VLAN_STATUS_CHOICES)
role = NestedRoleSerializer()
site = NestedSiteSerializer(required=False, allow_null=True)
group = NestedVLANGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=VLAN_STATUS_CHOICES, required=False)
role = NestedRoleSerializer(required=False, allow_null=True)
class Meta:
model = VLAN
@ -176,24 +154,6 @@ class VLANSerializer(CustomFieldModelSerializer):
'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name',
'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 = []
def validate(self, data):
@ -206,22 +166,30 @@ class WritableVLANSerializer(CustomFieldModelSerializer):
validator(data)
# Enforce model validation
super(WritableVLANSerializer, self).validate(data)
super(VLANSerializer, self).validate(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
#
class PrefixSerializer(CustomFieldModelSerializer):
site = NestedSiteSerializer()
vrf = NestedVRFSerializer()
tenant = NestedTenantSerializer()
vlan = NestedVLANSerializer()
status = ChoiceFieldSerializer(choices=PREFIX_STATUS_CHOICES)
role = NestedRoleSerializer()
site = NestedSiteSerializer(required=False, allow_null=True)
vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
vlan = NestedVLANSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=PREFIX_STATUS_CHOICES, required=False)
role = NestedRoleSerializer(required=False, allow_null=True)
class Meta:
model = Prefix
@ -229,9 +197,10 @@ class PrefixSerializer(CustomFieldModelSerializer):
'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
'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')
class Meta:
@ -239,16 +208,6 @@ class NestedPrefixSerializer(serializers.ModelSerializer):
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):
def to_representation(self, instance):
@ -288,11 +247,11 @@ class IPAddressInterfaceSerializer(serializers.ModelSerializer):
class IPAddressSerializer(CustomFieldModelSerializer):
vrf = NestedVRFSerializer()
tenant = NestedTenantSerializer()
status = ChoiceFieldSerializer(choices=IPADDRESS_STATUS_CHOICES)
role = ChoiceFieldSerializer(choices=IPADDRESS_ROLE_CHOICES)
interface = IPAddressInterfaceSerializer()
vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceFieldSerializer(choices=IPADDRESS_STATUS_CHOICES, required=False)
role = ChoiceFieldSerializer(choices=IPADDRESS_ROLE_CHOICES, required=False)
interface = IPAddressInterfaceSerializer(required=False, allow_null=True)
class Meta:
model = IPAddress
@ -300,9 +259,10 @@ class IPAddressSerializer(CustomFieldModelSerializer):
'id', 'family', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'description', 'nat_inside',
'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')
class Meta:
@ -310,18 +270,8 @@ class NestedIPAddressSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'family', 'address']
IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer()
IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer()
class WritableIPAddressSerializer(CustomFieldModelSerializer):
class Meta:
model = IPAddress
fields = [
'id', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'description', 'nat_inside',
'custom_fields', 'created', 'last_updated',
]
IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer(required=False, allow_null=True)
IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer(read_only=True)
class AvailableIPSerializer(serializers.Serializer):
@ -342,22 +292,11 @@ class AvailableIPSerializer(serializers.Serializer):
# Services
#
class ServiceSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
virtual_machine = NestedVirtualMachineSerializer()
class ServiceSerializer(ValidatedModelSerializer):
device = NestedDeviceSerializer(required=False, allow_null=True)
virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
protocol = ChoiceFieldSerializer(choices=IP_PROTOCOL_CHOICES)
ipaddresses = NestedIPAddressSerializer(many=True)
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):
ipaddresses = NestedIPAddressSerializer(many=True, required=False)
class Meta:
model = Service

View File

@ -35,7 +35,6 @@ class IPAMFieldChoicesViewSet(FieldChoicesViewSet):
class VRFViewSet(CustomFieldModelViewSet):
queryset = VRF.objects.select_related('tenant')
serializer_class = serializers.VRFSerializer
write_serializer_class = serializers.WritableVRFSerializer
filter_class = filters.VRFFilter
@ -56,7 +55,6 @@ class RIRViewSet(ModelViewSet):
class AggregateViewSet(CustomFieldModelViewSet):
queryset = Aggregate.objects.select_related('rir')
serializer_class = serializers.AggregateSerializer
write_serializer_class = serializers.WritableAggregateSerializer
filter_class = filters.AggregateFilter
@ -77,7 +75,6 @@ class RoleViewSet(ModelViewSet):
class PrefixViewSet(CustomFieldModelViewSet):
queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
serializer_class = serializers.PrefixSerializer
write_serializer_class = serializers.WritablePrefixSerializer
filter_class = filters.PrefixFilter
@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
if isinstance(request.data, list):
serializer = serializers.WritablePrefixSerializer(data=requested_prefixes, many=True)
serializer = serializers.PrefixSerializer(data=requested_prefixes, many=True)
else:
serializer = serializers.WritablePrefixSerializer(data=requested_prefixes[0])
serializer = serializers.PrefixSerializer(data=requested_prefixes[0])
# Create the new Prefix(es)
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
if isinstance(request.data, list):
serializer = serializers.WritableIPAddressSerializer(data=requested_ips, many=True)
serializer = serializers.IPAddressSerializer(data=requested_ips, many=True)
else:
serializer = serializers.WritableIPAddressSerializer(data=requested_ips[0])
serializer = serializers.IPAddressSerializer(data=requested_ips[0])
# Create the new IP address(es)
if serializer.is_valid():
@ -223,7 +220,6 @@ class IPAddressViewSet(CustomFieldModelViewSet):
'nat_outside'
)
serializer_class = serializers.IPAddressSerializer
write_serializer_class = serializers.WritableIPAddressSerializer
filter_class = filters.IPAddressFilter
@ -234,7 +230,6 @@ class IPAddressViewSet(CustomFieldModelViewSet):
class VLANGroupViewSet(ModelViewSet):
queryset = VLANGroup.objects.select_related('site')
serializer_class = serializers.VLANGroupSerializer
write_serializer_class = serializers.WritableVLANGroupSerializer
filter_class = filters.VLANGroupFilter
@ -245,7 +240,6 @@ class VLANGroupViewSet(ModelViewSet):
class VLANViewSet(CustomFieldModelViewSet):
queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role')
serializer_class = serializers.VLANSerializer
write_serializer_class = serializers.WritableVLANSerializer
filter_class = filters.VLANFilter
@ -256,5 +250,4 @@ class VLANViewSet(CustomFieldModelViewSet):
class ServiceViewSet(ModelViewSet):
queryset = Service.objects.select_related('device')
serializer_class = serializers.ServiceSerializer
write_serializer_class = serializers.WritableServiceSerializer
filter_class = filters.ServiceFilter

View File

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

View File

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

View File

@ -8,7 +8,7 @@ from dcim.models import Interface
from extras.api.customfields import CustomFieldModelSerializer
from ipam.models import IPAddress
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.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -24,7 +24,7 @@ class ClusterTypeSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug']
class NestedClusterTypeSerializer(serializers.ModelSerializer):
class NestedClusterTypeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail')
class Meta:
@ -43,7 +43,7 @@ class ClusterGroupSerializer(ValidatedModelSerializer):
fields = ['id', 'name', 'slug']
class NestedClusterGroupSerializer(serializers.ModelSerializer):
class NestedClusterGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail')
class Meta:
@ -57,15 +57,15 @@ class NestedClusterGroupSerializer(serializers.ModelSerializer):
class ClusterSerializer(CustomFieldModelSerializer):
type = NestedClusterTypeSerializer()
group = NestedClusterGroupSerializer()
site = NestedSiteSerializer()
group = NestedClusterGroupSerializer(required=False, allow_null=True)
site = NestedSiteSerializer(required=False, allow_null=True)
class Meta:
model = Cluster
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')
class Meta:
@ -73,13 +73,6 @@ class NestedClusterSerializer(serializers.ModelSerializer):
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
#
@ -94,14 +87,14 @@ class VirtualMachineIPAddressSerializer(serializers.ModelSerializer):
class VirtualMachineSerializer(CustomFieldModelSerializer):
status = ChoiceFieldSerializer(choices=VM_STATUS_CHOICES)
cluster = NestedClusterSerializer()
role = NestedDeviceRoleSerializer()
tenant = NestedTenantSerializer()
platform = NestedPlatformSerializer()
primary_ip = VirtualMachineIPAddressSerializer()
primary_ip4 = VirtualMachineIPAddressSerializer()
primary_ip6 = VirtualMachineIPAddressSerializer()
status = ChoiceFieldSerializer(choices=VM_STATUS_CHOICES, required=False)
cluster = NestedClusterSerializer(required=False, allow_null=True)
role = NestedDeviceRoleSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
platform = NestedPlatformSerializer(required=False, allow_null=True)
primary_ip = VirtualMachineIPAddressSerializer(read_only=True)
primary_ip4 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
primary_ip6 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
class Meta:
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')
class Meta:
@ -119,22 +112,13 @@ class NestedVirtualMachineSerializer(serializers.ModelSerializer):
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
#
class InterfaceSerializer(serializers.ModelSerializer):
class InterfaceSerializer(ValidatedModelSerializer):
virtual_machine = NestedVirtualMachineSerializer()
form_factor = serializers.IntegerField(default=IFACE_FF_VIRTUAL)
class Meta:
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')
class Meta:
model = Interface
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):
queryset = Cluster.objects.select_related('type', 'group')
serializer_class = serializers.ClusterSerializer
write_serializer_class = serializers.WritableClusterSerializer
filter_class = filters.ClusterFilter
@ -48,12 +47,10 @@ class ClusterViewSet(CustomFieldModelViewSet):
class VirtualMachineViewSet(CustomFieldModelViewSet):
queryset = VirtualMachine.objects.all()
serializer_class = serializers.VirtualMachineSerializer
write_serializer_class = serializers.WritableVirtualMachineSerializer
filter_class = filters.VirtualMachineFilter
class InterfaceViewSet(ModelViewSet):
queryset = Interface.objects.filter(virtual_machine__isnull=False).select_related('virtual_machine')
serializer_class = serializers.InterfaceSerializer
write_serializer_class = serializers.WritableInterfaceSerializer
filter_class = filters.InterfaceFilter