Implemented static writable ModelSerializers for all models

This commit is contained in:
Jeremy Stretch 2017-01-31 15:35:09 -05:00
parent e1cd846c9a
commit bb1f97abc2
13 changed files with 251 additions and 140 deletions

View File

@ -2,7 +2,7 @@ from rest_framework import serializers
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
from dcim.api.serializers import NestedSiteSerializer, DeviceInterfaceSerializer
from extras.api.serializers import CustomFieldSerializer
from extras.api.serializers import CustomFieldValueSerializer
from tenancy.api.serializers import NestedTenantSerializer
@ -10,17 +10,18 @@ from tenancy.api.serializers import NestedTenantSerializer
# Providers
#
class ProviderSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class ProviderSerializer(serializers.ModelSerializer):
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Provider
fields = [
'id', 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
'custom_fields',
'custom_field_values',
]
class NestedProviderSerializer(serializers.HyperlinkedModelSerializer):
class NestedProviderSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:provider-detail')
class Meta:
@ -28,6 +29,15 @@ class NestedProviderSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'slug']
class WritableProviderSerializer(serializers.ModelSerializer):
class Meta:
model = Provider
fields = [
'id', 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
]
#
# Circuit types
#
@ -39,7 +49,7 @@ class CircuitTypeSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug']
class NestedCircuitTypeSerializer(serializers.HyperlinkedModelSerializer):
class NestedCircuitTypeSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittype-detail')
class Meta:
@ -64,20 +74,21 @@ class CircuitTerminationSerializer(serializers.ModelSerializer):
# Circuits
#
class CircuitSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class CircuitSerializer(serializers.ModelSerializer):
provider = NestedProviderSerializer()
type = NestedCircuitTypeSerializer()
tenant = NestedTenantSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Circuit
fields = [
'id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
'custom_fields',
'custom_field_values',
]
class NestedCircuitSerializer(serializers.HyperlinkedModelSerializer):
class NestedCircuitSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuit-detail')
class Meta:
@ -85,12 +96,10 @@ class NestedCircuitSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'cid']
# TODO: Delete this
class CircuitDetailSerializer(CircuitSerializer):
terminations = CircuitTerminationSerializer(many=True)
class WritableCircuitSerializer(serializers.ModelSerializer):
class Meta(CircuitSerializer.Meta):
class Meta:
model = Circuit
fields = [
'id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
'terminations', 'custom_fields',
]

View File

@ -2,9 +2,6 @@ from django.conf.urls import include, url
from rest_framework import routers
from extras.models import GRAPH_TYPE_PROVIDER
from extras.api.views import GraphListView
from . import views

View File

@ -21,9 +21,10 @@ from . import serializers
# Providers
#
class ProviderViewSet(CustomFieldModelViewSet):
class ProviderViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Provider.objects.all()
serializer_class = serializers.ProviderSerializer
write_serializer_class = serializers.WritableProviderSerializer
@detail_route()
def graphs(self, request, pk=None):
@ -49,6 +50,7 @@ class CircuitTypeViewSet(ModelViewSet):
class CircuitViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Circuit.objects.select_related('type', 'tenant', 'provider')
serializer_class = serializers.CircuitSerializer
write_serializer_class = serializers.WritableCircuitSerializer
filter_class = CircuitFilter

View File

@ -4,10 +4,10 @@ from ipam.models import IPAddress
from dcim.models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceType,
DeviceRole, Interface, InterfaceConnection, InterfaceTemplate, Manufacturer, Module, Platform, PowerOutlet,
PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackRole, RACK_FACE_FRONT, RACK_FACE_REAR, Site,
SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT,
PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackRole, Site, SUBDEVICE_ROLE_CHILD,
SUBDEVICE_ROLE_PARENT,
)
from extras.api.serializers import CustomFieldSerializer
from extras.api.serializers import CustomFieldValueSerializer
from tenancy.api.serializers import NestedTenantSerializer
@ -15,19 +15,20 @@ from tenancy.api.serializers import NestedTenantSerializer
# Sites
#
class SiteSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class SiteSerializer(serializers.ModelSerializer):
tenant = NestedTenantSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Site
fields = [
'id', 'name', 'slug', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address', 'contact_name',
'contact_phone', 'contact_email', 'comments', 'custom_fields', 'count_prefixes', 'count_vlans',
'contact_phone', 'contact_email', 'comments', 'custom_field_values', 'count_prefixes', 'count_vlans',
'count_racks', 'count_devices', 'count_circuits',
]
class NestedSiteSerializer(serializers.HyperlinkedModelSerializer):
class NestedSiteSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail')
class Meta:
@ -35,6 +36,16 @@ class NestedSiteSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'slug']
class WritableSiteSerializer(serializers.ModelSerializer):
class Meta:
model = Site
fields = [
'id', 'name', 'slug', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address', 'contact_name',
'contact_phone', 'contact_email', 'comments',
]
#
# Rack groups
#
@ -47,7 +58,7 @@ class RackGroupSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'site']
class NestedRackGroupSerializer(serializers.HyperlinkedModelSerializer):
class NestedRackGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackgroup-detail')
class Meta:
@ -55,6 +66,13 @@ class NestedRackGroupSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'slug']
class WritableRackGroupSerializer(serializers.ModelSerializer):
class Meta:
model = RackGroup
fields = ['id', 'name', 'slug', 'site']
#
# Rack roles
#
@ -66,7 +84,7 @@ class RackRoleSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'color']
class NestedRackRoleSerializer(serializers.HyperlinkedModelSerializer):
class NestedRackRoleSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackrole-detail')
class Meta:
@ -79,21 +97,22 @@ class NestedRackRoleSerializer(serializers.HyperlinkedModelSerializer):
#
class RackSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class RackSerializer(serializers.ModelSerializer):
site = NestedSiteSerializer()
group = NestedRackGroupSerializer()
tenant = NestedTenantSerializer()
role = NestedRackRoleSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Rack
fields = [
'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width', 'u_height',
'desc_units', 'comments', 'custom_fields',
'desc_units', 'comments', 'custom_field_values',
]
class NestedRackSerializer(serializers.HyperlinkedModelSerializer):
class NestedRackSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rack-detail')
class Meta:
@ -101,28 +120,15 @@ class NestedRackSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'display_name']
class RackDetailSerializer(RackSerializer):
front_units = serializers.SerializerMethodField()
rear_units = serializers.SerializerMethodField()
class WritableRackSerializer(serializers.ModelSerializer):
class Meta(RackSerializer.Meta):
class Meta:
model = Rack
fields = [
'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width', 'u_height',
'desc_units', 'comments', 'custom_fields', 'front_units', 'rear_units',
'id', 'name', 'facility_id', 'site', 'group', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
'comments',
]
def get_front_units(self, obj):
units = obj.get_rack_units(face=RACK_FACE_FRONT)
for u in units:
u['device'] = NestedDeviceSerializer(u['device']).data if u['device'] else None
return units
def get_rear_units(self, obj):
units = obj.get_rack_units(face=RACK_FACE_REAR)
for u in units:
u['device'] = NestedDeviceSerializer(u['device']).data if u['device'] else None
return units
#
# Manufacturers
@ -135,7 +141,7 @@ class ManufacturerSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug']
class NestedManufacturerSerializer(serializers.HyperlinkedModelSerializer):
class NestedManufacturerSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:manufacturer-detail')
class Meta:
@ -147,16 +153,17 @@ class NestedManufacturerSerializer(serializers.HyperlinkedModelSerializer):
# Device types
#
class DeviceTypeSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class DeviceTypeSerializer(serializers.ModelSerializer):
manufacturer = NestedManufacturerSerializer()
subdevice_role = serializers.SerializerMethodField()
instance_count = serializers.IntegerField(source='instances.count', read_only=True)
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = DeviceType
fields = [
'id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'interface_ordering',
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_field_values',
'instance_count',
]
@ -168,7 +175,7 @@ class DeviceTypeSerializer(CustomFieldSerializer, serializers.ModelSerializer):
}[obj.subdevice_role]
class NestedDeviceTypeSerializer(serializers.HyperlinkedModelSerializer):
class NestedDeviceTypeSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicetype-detail')
manufacturer = NestedManufacturerSerializer()
@ -177,6 +184,16 @@ class NestedDeviceTypeSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'manufacturer', 'model', 'slug']
class WritableDeviceTypeSerializer(serializers.ModelSerializer):
class Meta:
model = DeviceType
fields = [
'id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'interface_ordering',
'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments',
]
class ConsolePortTemplateSerializer(serializers.ModelSerializer):
class Meta:
@ -230,7 +247,7 @@ class DeviceRoleSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'color']
class NestedDeviceRoleSerializer(serializers.HyperlinkedModelSerializer):
class NestedDeviceRoleSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicerole-detail')
class Meta:
@ -249,7 +266,7 @@ class PlatformSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'rpc_client']
class NestedPlatformSerializer(serializers.HyperlinkedModelSerializer):
class NestedPlatformSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:platform-detail')
class Meta:
@ -262,7 +279,7 @@ class NestedPlatformSerializer(serializers.HyperlinkedModelSerializer):
#
# Cannot import ipam.api.NestedIPAddressSerializer due to circular dependency
class DeviceIPAddressSerializer(serializers.HyperlinkedModelSerializer):
class DeviceIPAddressSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
class Meta:
@ -270,7 +287,7 @@ class DeviceIPAddressSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'family', 'address']
class DeviceSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class DeviceSerializer(serializers.ModelSerializer):
device_type = NestedDeviceTypeSerializer()
device_role = NestedDeviceRoleSerializer()
tenant = NestedTenantSerializer()
@ -280,13 +297,14 @@ class DeviceSerializer(CustomFieldSerializer, serializers.ModelSerializer):
primary_ip4 = DeviceIPAddressSerializer()
primary_ip6 = DeviceIPAddressSerializer()
parent_device = serializers.SerializerMethodField()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Device
fields = [
'id', 'name', 'display_name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
'rack', 'position', 'face', 'parent_device', 'status', 'primary_ip', 'primary_ip4', 'primary_ip6',
'comments', 'custom_fields',
'comments', 'custom_field_values',
]
def get_parent_device(self, obj):
@ -304,7 +322,7 @@ class DeviceSerializer(CustomFieldSerializer, serializers.ModelSerializer):
}
class NestedDeviceSerializer(serializers.HyperlinkedModelSerializer):
class NestedDeviceSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
class Meta:
@ -312,19 +330,29 @@ class NestedDeviceSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'display_name']
class WritableDeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = [
'id', 'name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag', 'rack',
'position', 'face', 'status', 'primary_ip4', 'primary_ip6', 'comments',
]
#
# Console server ports
#
class ConsoleServerPortSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
class Meta:
model = ConsoleServerPort
fields = ['id', 'device', 'name', 'connected_console']
class DeviceConsoleServerPortSerializer(serializers.HyperlinkedModelSerializer):
class DeviceConsoleServerPortSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail')
class Meta:
@ -338,7 +366,7 @@ class DeviceConsoleServerPortSerializer(serializers.HyperlinkedModelSerializer):
#
class ConsolePortSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
cs_port = ConsoleServerPortSerializer()
class Meta:
@ -346,7 +374,7 @@ class ConsolePortSerializer(serializers.ModelSerializer):
fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
class DeviceConsolePortSerializer(serializers.HyperlinkedModelSerializer):
class DeviceConsolePortSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail')
class Meta:
@ -360,14 +388,14 @@ class DeviceConsolePortSerializer(serializers.HyperlinkedModelSerializer):
#
class PowerOutletSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
class Meta:
model = PowerOutlet
fields = ['id', 'device', 'name', 'connected_port']
class DevicePowerOutletSerializer(serializers.HyperlinkedModelSerializer):
class DevicePowerOutletSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail')
class Meta:
@ -381,7 +409,7 @@ class DevicePowerOutletSerializer(serializers.HyperlinkedModelSerializer):
#
class PowerPortSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
power_outlet = PowerOutletSerializer()
class Meta:
@ -389,7 +417,7 @@ class PowerPortSerializer(serializers.ModelSerializer):
fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
class DevicePowerPortSerializer(serializers.HyperlinkedModelSerializer):
class DevicePowerPortSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail')
class Meta:
@ -404,7 +432,7 @@ class DevicePowerPortSerializer(serializers.HyperlinkedModelSerializer):
class InterfaceSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
connection = serializers.SerializerMethodField(read_only=True)
connected_interface = serializers.SerializerMethodField(read_only=True)
@ -426,7 +454,7 @@ class InterfaceSerializer(serializers.ModelSerializer):
return None
class PeerInterfaceSerializer(serializers.HyperlinkedModelSerializer):
class PeerInterfaceSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
device = NestedDeviceSerializer()
@ -435,7 +463,7 @@ class PeerInterfaceSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description']
class DeviceInterfaceSerializer(serializers.HyperlinkedModelSerializer):
class DeviceInterfaceSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
connection = serializers.SerializerMethodField()
@ -462,7 +490,7 @@ class InterfaceConnectionSerializer(serializers.ModelSerializer):
fields = ['id', 'interface_a', 'interface_b', 'connection_status']
class NestedInterfaceConnectionSerializer(serializers.HyperlinkedModelSerializer):
class NestedInterfaceConnectionSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfaceconnection-detail')
class Meta:
@ -470,12 +498,19 @@ class NestedInterfaceConnectionSerializer(serializers.HyperlinkedModelSerializer
fields = ['id', 'url', 'connection_status']
class WritableInterfaceConnectionSerializer(serializers.ModelSerializer):
class Meta:
model = InterfaceConnection
fields = ['id', 'interface_a', 'interface_b', 'connection_status']
#
# Device bays
#
class DeviceBaySerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
installed_device = NestedDeviceSerializer()
class Meta:
@ -483,7 +518,7 @@ class DeviceBaySerializer(serializers.ModelSerializer):
fields = ['id', 'device', 'name', 'installed_device']
class DeviceDeviceBaySerializer(serializers.HyperlinkedModelSerializer):
class DeviceDeviceBaySerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebay-detail')
class Meta:
@ -497,7 +532,7 @@ class DeviceDeviceBaySerializer(serializers.HyperlinkedModelSerializer):
#
class ModuleSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
device = NestedDeviceSerializer(read_only=True)
manufacturer = NestedManufacturerSerializer()
class Meta:
@ -505,7 +540,7 @@ class ModuleSerializer(serializers.ModelSerializer):
fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
class DeviceModuleSerializer(serializers.HyperlinkedModelSerializer):
class DeviceModuleSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:module-detail')
manufacturer = NestedManufacturerSerializer()

View File

@ -2,10 +2,8 @@ from django.conf.urls import include, url
from rest_framework import routers
from extras.models import GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.api.views import GraphListView, TopologyMapView
from extras.api.views import TopologyMapView
from ipam.api.views import ServiceViewSet, DeviceServiceViewSet
from . import views

View File

@ -33,6 +33,7 @@ from . import serializers
class SiteViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Site.objects.select_related('tenant')
serializer_class = serializers.SiteSerializer
write_serializer_class = serializers.WritableSiteSerializer
@detail_route()
def graphs(self, request, pk=None):
@ -50,6 +51,7 @@ class RackGroupViewSet(WritableSerializerMixin, ModelViewSet):
queryset = RackGroup.objects.select_related('site')
serializer_class = serializers.RackGroupSerializer
filter_class = filters.RackGroupFilter
write_serializer_class = serializers.WritableRackGroupSerializer
#
@ -68,6 +70,7 @@ class RackRoleViewSet(ModelViewSet):
class RackViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Rack.objects.select_related('site', 'group__site', 'tenant')
serializer_class = serializers.RackSerializer
write_serializer_class = serializers.WritableRackSerializer
filter_class = filters.RackFilter
@detail_route(url_path='rack-units')
@ -112,6 +115,7 @@ class ManufacturerViewSet(ModelViewSet):
class DeviceTypeViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = DeviceType.objects.select_related('manufacturer')
serializer_class = serializers.DeviceTypeSerializer
write_serializer_class = serializers.WritableDeviceTypeSerializer
#
@ -143,6 +147,7 @@ class DeviceViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
'primary_ip4__nat_outside', 'primary_ip6__nat_outside',
)
serializer_class = serializers.DeviceSerializer
write_serializer_class = serializers.WritableDeviceSerializer
filter_class = filters.DeviceFilter
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer, FlatJSONRenderer]
@ -335,9 +340,10 @@ class DeviceModuleViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
# Interface connections
#
class InterfaceConnectionViewSet(ModelViewSet):
class InterfaceConnectionViewSet(WritableSerializerMixin, ModelViewSet):
queryset = InterfaceConnection.objects.select_related('interface_a__device', 'interface_b__device')
serializer_class = serializers.InterfaceConnectionSerializer
write_serializer_class = serializers.WritableInterfaceConnectionSerializer
#

View File

@ -1,35 +1,42 @@
from rest_framework import serializers
from extras.models import CF_TYPE_SELECT, CustomFieldChoice, Graph
from extras.models import CF_TYPE_SELECT, CustomFieldChoice, CustomFieldValue, Graph
class CustomFieldSerializer(serializers.Serializer):
"""
Extends a ModelSerializer to render any CustomFields and their values associated with an object.
"""
custom_fields = serializers.SerializerMethodField()
# class CustomFieldSerializer(serializers.ModelSerializer):
# """
# Extends ModelSerializer to render any CustomFields and their values associated with an object.
# """
# custom_fields = serializers.SerializerMethodField()
#
# def get_custom_fields(self, obj):
#
# # Gather all CustomFields applicable to this object
# fields = {cf.name: None for cf in self.context['custom_fields']}
# custom_field_choices = self.context['custom_field_choices']
#
# # Attach any defined CustomFieldValues to their respective CustomFields
# for cfv in obj.custom_field_values.all():
#
# # Attempt to suppress database lookups for CustomFieldChoices by using the cached choice set from the view
# # context.
# if cfv.field.type == CF_TYPE_SELECT:
# cfc = {
# 'id': int(cfv.serialized_value),
# 'value': custom_field_choices[int(cfv.serialized_value)]
# }
# fields[cfv.field.name] = CustomFieldChoiceSerializer(instance=cfc).data
# else:
# fields[cfv.field.name] = cfv.value
#
# return fields
def get_custom_fields(self, obj):
# Gather all CustomFields applicable to this object
fields = {cf.name: None for cf in self.context['custom_fields']}
custom_field_choices = self.context['custom_field_choices']
class CustomFieldValueSerializer(serializers.ModelSerializer):
# Attach any defined CustomFieldValues to their respective CustomFields
for cfv in obj.custom_field_values.all():
# Attempt to suppress database lookups for CustomFieldChoices by using the cached choice set from the view
# context.
if cfv.field.type == CF_TYPE_SELECT:
cfc = {
'id': int(cfv.serialized_value),
'value': custom_field_choices[int(cfv.serialized_value)]
}
fields[cfv.field.name] = CustomFieldChoiceSerializer(instance=cfc).data
else:
fields[cfv.field.name] = cfv.value
return fields
class Meta:
model = CustomFieldValue
fields = ['field', 'serialized_value']
class CustomFieldChoiceSerializer(serializers.ModelSerializer):

View File

@ -1,25 +1,25 @@
from rest_framework import serializers
from dcim.api.serializers import NestedDeviceSerializer, DeviceInterfaceSerializer, NestedSiteSerializer
from extras.api.serializers import CustomFieldSerializer
from extras.api.serializers import CustomFieldValueSerializer
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import WritableSerializerMixin
#
# VRFs
#
class VRFSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class VRFSerializer(serializers.ModelSerializer):
tenant = NestedTenantSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = VRF
fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_fields']
fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_field_values']
class NestedVRFSerializer(serializers.HyperlinkedModelSerializer):
class NestedVRFSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail')
class Meta:
@ -27,6 +27,13 @@ class NestedVRFSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'rd']
class WritableVRFSerializer(serializers.ModelSerializer):
class Meta:
model = VRF
fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description']
#
# Roles
#
@ -38,7 +45,7 @@ class RoleSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'weight']
class NestedRoleSerializer(serializers.HyperlinkedModelSerializer):
class NestedRoleSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail')
class Meta:
@ -57,7 +64,7 @@ class RIRSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'is_private']
class NestedRIRSerializer(serializers.HyperlinkedModelSerializer):
class NestedRIRSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail')
class Meta:
@ -69,15 +76,16 @@ class NestedRIRSerializer(serializers.HyperlinkedModelSerializer):
# Aggregates
#
class AggregateSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class AggregateSerializer(serializers.ModelSerializer):
rir = NestedRIRSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Aggregate
fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_fields']
fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_field_values']
class NestedAggregateSerializer(serializers.HyperlinkedModelSerializer):
class NestedAggregateSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail')
class Meta(AggregateSerializer.Meta):
@ -85,11 +93,18 @@ class NestedAggregateSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'family', 'prefix']
class WritableAggregateSerializer(serializers.ModelSerializer):
class Meta:
model = Aggregate
fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description']
#
# VLAN groups
#
class VLANGroupSerializer(WritableSerializerMixin, serializers.ModelSerializer):
class VLANGroupSerializer(serializers.ModelSerializer):
site = NestedSiteSerializer()
class Meta:
@ -97,7 +112,7 @@ class VLANGroupSerializer(WritableSerializerMixin, serializers.ModelSerializer):
fields = ['id', 'name', 'slug', 'site']
class NestedVLANGroupSerializer(serializers.HyperlinkedModelSerializer):
class NestedVLANGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlangroup-detail')
class Meta:
@ -105,25 +120,33 @@ class NestedVLANGroupSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'name', 'slug']
class WritableVLANGroupSerializer(serializers.ModelSerializer):
class Meta:
model = VLANGroup
fields = ['id', 'name', 'slug', 'site']
#
# VLANs
#
class VLANSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class VLANSerializer(serializers.ModelSerializer):
site = NestedSiteSerializer()
group = NestedVLANGroupSerializer()
tenant = NestedTenantSerializer()
role = NestedRoleSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = VLAN
fields = [
'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name',
'custom_fields',
'custom_field_values',
]
class NestedVLANSerializer(serializers.HyperlinkedModelSerializer):
class NestedVLANSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
class Meta:
@ -131,26 +154,36 @@ class NestedVLANSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'vid', 'name', 'display_name']
class WritableVLANSerializer(serializers.ModelSerializer):
class Meta:
model = VLAN
fields = [
'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description',
]
#
# Prefixes
#
class PrefixSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class PrefixSerializer(serializers.ModelSerializer):
site = NestedSiteSerializer()
vrf = NestedVRFSerializer()
tenant = NestedTenantSerializer()
vlan = NestedVLANSerializer()
role = NestedRoleSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Prefix
fields = [
'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
'custom_fields',
'custom_field_values',
]
class NestedPrefixSerializer(serializers.HyperlinkedModelSerializer):
class NestedPrefixSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:prefix-detail')
class Meta:
@ -158,24 +191,34 @@ class NestedPrefixSerializer(serializers.HyperlinkedModelSerializer):
fields = ['id', 'url', 'family', 'prefix']
class WritablePrefixSerializer(serializers.ModelSerializer):
class Meta:
model = Prefix
fields = [
'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
]
#
# IP addresses
#
class IPAddressSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class IPAddressSerializer(serializers.ModelSerializer):
vrf = NestedVRFSerializer()
tenant = NestedTenantSerializer()
interface = DeviceInterfaceSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = IPAddress
fields = [
'id', 'family', 'address', 'vrf', 'tenant', 'status', 'interface', 'description', 'nat_inside',
'nat_outside', 'custom_fields',
'nat_outside', 'custom_field_values',
]
class NestedIPAddressSerializer(serializers.HyperlinkedModelSerializer):
class NestedIPAddressSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail')
class Meta:
@ -186,6 +229,13 @@ IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer()
IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer()
class WritableIPAddressSerializer(serializers.ModelSerializer):
class Meta:
model = IPAddress
fields = ['id', 'family', 'address', 'vrf', 'tenant', 'status', 'interface', 'description', 'nat_inside']
#
# Services
#
@ -199,7 +249,7 @@ class ServiceSerializer(serializers.ModelSerializer):
fields = ['id', 'device', 'name', 'port', 'protocol', 'ipaddresses', 'description']
class DeviceServiceSerializer(serializers.HyperlinkedModelSerializer):
class DeviceServiceSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:service-detail')
ipaddresses = NestedIPAddressSerializer(many=True)

View File

@ -20,6 +20,7 @@ from . import serializers
class VRFViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = VRF.objects.select_related('tenant')
serializer_class = serializers.VRFSerializer
write_serializer_class = serializers.WritableVRFSerializer
filter_class = filters.VRFFilter
@ -48,6 +49,7 @@ class RIRViewSet(ModelViewSet):
class AggregateViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Aggregate.objects.select_related('rir')
serializer_class = serializers.AggregateSerializer
write_serializer_class = serializers.WritableAggregateSerializer
filter_class = filters.AggregateFilter
@ -58,6 +60,7 @@ class AggregateViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
class PrefixViewSet(WritableSerializerMixin, 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
@ -68,6 +71,7 @@ class PrefixViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
class IPAddressViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device', 'nat_inside')
serializer_class = serializers.IPAddressSerializer
write_serializer_class = serializers.WritableIPAddressSerializer
filter_class = filters.IPAddressFilter
@ -78,6 +82,7 @@ class IPAddressViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
class VLANGroupViewSet(WritableSerializerMixin, ModelViewSet):
queryset = VLANGroup.objects.select_related('site')
serializer_class = serializers.VLANGroupSerializer
write_serializer_class = serializers.WritableVLANGroupSerializer
filter_class = filters.VLANGroupFilter
@ -88,6 +93,7 @@ class VLANGroupViewSet(WritableSerializerMixin, ModelViewSet):
class VLANViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role')
serializer_class = serializers.VLANSerializer
write_serializer_class = serializers.WritableVLANSerializer
filter_class = filters.VLANFilter

View File

@ -15,7 +15,7 @@ class SecretRoleSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug']
class NestedSecretRoleSerializer(serializers.HyperlinkedModelSerializer):
class NestedSecretRoleSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='secrets-api:secretrole-detail')
class Meta:

View File

@ -1,6 +1,6 @@
from rest_framework import serializers
from extras.api.serializers import CustomFieldSerializer
from extras.api.serializers import CustomFieldValueSerializer
from tenancy.models import Tenant, TenantGroup
@ -15,7 +15,7 @@ class TenantGroupSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'slug']
class NestedTenantGroupSerializer(serializers.HyperlinkedModelSerializer):
class NestedTenantGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenantgroup-detail')
class Meta:
@ -27,17 +27,25 @@ class NestedTenantGroupSerializer(serializers.HyperlinkedModelSerializer):
# Tenants
#
class TenantSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class TenantSerializer(serializers.ModelSerializer):
group = NestedTenantGroupSerializer()
custom_field_values = CustomFieldValueSerializer(many=True)
class Meta:
model = Tenant
fields = ['id', 'name', 'slug', 'group', 'description', 'comments', 'custom_fields']
fields = ['id', 'name', 'slug', 'group', 'description', 'comments', 'custom_field_values']
class NestedTenantSerializer(serializers.HyperlinkedModelSerializer):
class NestedTenantSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenant-detail')
class Meta:
model = Tenant
fields = ['id', 'url', 'name', 'slug']
class WritableTenantSerializer(serializers.ModelSerializer):
class Meta:
model = Tenant
fields = ['id', 'name', 'slug', 'group', 'description', 'comments']

View File

@ -24,4 +24,5 @@ class TenantGroupViewSet(ModelViewSet):
class TenantViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = Tenant.objects.select_related('group')
serializer_class = serializers.TenantSerializer
write_serializer_class = serializers.WritableTenantSerializer
filter_class = TenantFilter

View File

@ -12,18 +12,10 @@ class ServiceUnavailable(APIException):
class WritableSerializerMixin(object):
"""
Returns a flat Serializer from the given model suitable for write operations (POST, PUT, PATCH). This is necessary
to allow write operations on objects which utilize nested serializers.
Allow for the use of an alternate, writable serializer class for write operations (e.g. POST, PUT).
"""
def get_serializer_class(self):
class WritableSerializer(ModelSerializer):
class Meta(self.serializer_class.Meta):
pass
if self.action in WRITE_OPERATIONS:
return WritableSerializer
if self.action in WRITE_OPERATIONS and hasattr(self, 'write_serializer_class'):
return self.write_serializer_class
return self.serializer_class