Browse Source

Re-implemented CustomFieldSerializer (read-only for now)

Jeremy Stretch 8 years ago
parent
commit
0e04d20762

+ 5 - 7
netbox/circuits/api/serializers.py

@@ -2,7 +2,7 @@ from rest_framework import serializers
 
 from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
 from dcim.api.serializers import NestedSiteSerializer, InterfaceSerializer
-from extras.api.serializers import CustomFieldValueSerializer
+from extras.api.serializers import CustomFieldModelSerializer
 from tenancy.api.serializers import NestedTenantSerializer
 
 
@@ -10,14 +10,13 @@ from tenancy.api.serializers import NestedTenantSerializer
 # Providers
 #
 
-class ProviderSerializer(serializers.ModelSerializer):
-    custom_field_values = CustomFieldValueSerializer(many=True)
+class ProviderSerializer(CustomFieldModelSerializer):
 
     class Meta:
         model = Provider
         fields = [
             'id', 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
-            'custom_field_values',
+            'custom_fields',
         ]
 
 
@@ -61,17 +60,16 @@ class NestedCircuitTypeSerializer(serializers.ModelSerializer):
 # Circuits
 #
 
-class CircuitSerializer(serializers.ModelSerializer):
+class CircuitSerializer(CustomFieldModelSerializer):
     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_field_values',
+            'custom_fields',
         ]
 
 

+ 9 - 13
netbox/dcim/api/serializers.py

@@ -8,7 +8,7 @@ from dcim.models import (
     PowerPortTemplate, Rack, RackGroup, RackRole, RACK_FACE_CHOICES, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, Site,
     STATUS_CHOICES, SUBDEVICE_ROLE_CHOICES,
 )
-from extras.api.serializers import CustomFieldValueSerializer
+from extras.api.serializers import CustomFieldModelSerializer
 from tenancy.api.serializers import NestedTenantSerializer
 from utilities.api import ChoiceFieldSerializer
 
@@ -17,15 +17,14 @@ from utilities.api import ChoiceFieldSerializer
 # Sites
 #
 
-class SiteSerializer(serializers.ModelSerializer):
+class SiteSerializer(CustomFieldModelSerializer):
     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_field_values', 'count_prefixes', 'count_vlans',
+            'contact_phone', 'contact_email', 'comments', 'custom_fields', 'count_prefixes', 'count_vlans',
             'count_racks', 'count_devices', 'count_circuits',
         ]
 
@@ -99,20 +98,19 @@ class NestedRackRoleSerializer(serializers.ModelSerializer):
 #
 
 
-class RackSerializer(serializers.ModelSerializer):
+class RackSerializer(CustomFieldModelSerializer):
     site = NestedSiteSerializer()
     group = NestedRackGroupSerializer()
     tenant = NestedTenantSerializer()
     role = NestedRackRoleSerializer()
     type = ChoiceFieldSerializer(choices=RACK_TYPE_CHOICES)
     width = ChoiceFieldSerializer(choices=RACK_WIDTH_CHOICES)
-    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_field_values',
+            'desc_units', 'comments', 'custom_fields',
         ]
 
 
@@ -157,18 +155,17 @@ class NestedManufacturerSerializer(serializers.ModelSerializer):
 # Device types
 #
 
-class DeviceTypeSerializer(serializers.ModelSerializer):
+class DeviceTypeSerializer(CustomFieldModelSerializer):
     manufacturer = NestedManufacturerSerializer()
     interface_ordering = ChoiceFieldSerializer(choices=IFACE_ORDERING_CHOICES)
     subdevice_role = ChoiceFieldSerializer(choices=SUBDEVICE_ROLE_CHOICES)
     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_field_values',
+            'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
             'instance_count',
         ]
 
@@ -358,7 +355,7 @@ class DeviceIPAddressSerializer(serializers.ModelSerializer):
         fields = ['id', 'url', 'family', 'address']
 
 
-class DeviceSerializer(serializers.ModelSerializer):
+class DeviceSerializer(CustomFieldModelSerializer):
     device_type = NestedDeviceTypeSerializer()
     device_role = NestedDeviceRoleSerializer()
     tenant = NestedTenantSerializer()
@@ -370,14 +367,13 @@ class DeviceSerializer(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_field_values',
+            'comments', 'custom_fields',
         ]
 
     def get_parent_device(self, obj):

+ 31 - 36
netbox/extras/api/serializers.py

@@ -1,42 +1,37 @@
+from django.contrib.contenttypes.models import ContentType
+
 from rest_framework import serializers
 
-from extras.models import CF_TYPE_SELECT, CustomFieldChoice, CustomFieldValue, Graph
-
-
-# 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
-
-
-class CustomFieldValueSerializer(serializers.ModelSerializer):
+from extras.models import CustomField, CustomFieldChoice, Graph
 
-    class Meta:
-        model = CustomFieldValue
-        fields = ['field', 'serialized_value']
+
+class CustomFieldSerializer(serializers.BaseSerializer):
+    """
+    Extends ModelSerializer to render any CustomFields and their values associated with an object.
+    """
+
+    def to_representation(self, manager):
+
+        # Initialize custom fields dictionary
+        data = {f.name: None for f in self.parent._custom_fields}
+
+        # Assign CustomFieldValues from database
+        for cfv in manager.all():
+            data[cfv.field.name] = cfv.value
+
+        return data
+
+
+class CustomFieldModelSerializer(serializers.ModelSerializer):
+    custom_fields = CustomFieldSerializer(source='custom_field_values')
+
+    def __init__(self, *args, **kwargs):
+
+        super(CustomFieldModelSerializer, self).__init__(*args, **kwargs)
+
+        # Cache the list of custom fields for this model
+        content_type = ContentType.objects.get_for_model(self.Meta.model)
+        self._custom_fields = CustomField.objects.filter(obj_type=content_type)
 
 
 class CustomFieldChoiceSerializer(serializers.ModelSerializer):

+ 11 - 16
netbox/ipam/api/serializers.py

@@ -1,7 +1,7 @@
 from rest_framework import serializers
 
 from dcim.api.serializers import NestedDeviceSerializer, InterfaceSerializer, NestedSiteSerializer
-from extras.api.serializers import CustomFieldValueSerializer
+from extras.api.serializers import CustomFieldModelSerializer
 from ipam.models import (
     Aggregate, IPAddress, IPADDRESS_STATUS_CHOICES, IP_PROTOCOL_CHOICES, Prefix, PREFIX_STATUS_CHOICES, RIR, Role,
     Service, VLAN, VLAN_STATUS_CHOICES, VLANGroup, VRF,
@@ -14,13 +14,12 @@ from utilities.api import ChoiceFieldSerializer
 # VRFs
 #
 
-class VRFSerializer(serializers.ModelSerializer):
+class VRFSerializer(CustomFieldModelSerializer):
     tenant = NestedTenantSerializer()
-    custom_field_values = CustomFieldValueSerializer(many=True)
 
     class Meta:
         model = VRF
-        fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_field_values']
+        fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_fields']
 
 
 class NestedVRFSerializer(serializers.ModelSerializer):
@@ -80,13 +79,12 @@ class NestedRIRSerializer(serializers.ModelSerializer):
 # Aggregates
 #
 
-class AggregateSerializer(serializers.ModelSerializer):
+class AggregateSerializer(CustomFieldModelSerializer):
     rir = NestedRIRSerializer()
-    custom_field_values = CustomFieldValueSerializer(many=True)
 
     class Meta:
         model = Aggregate
-        fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_field_values']
+        fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_fields']
 
 
 class NestedAggregateSerializer(serializers.ModelSerializer):
@@ -135,19 +133,18 @@ class WritableVLANGroupSerializer(serializers.ModelSerializer):
 # VLANs
 #
 
-class VLANSerializer(serializers.ModelSerializer):
+class VLANSerializer(CustomFieldModelSerializer):
     site = NestedSiteSerializer()
     group = NestedVLANGroupSerializer()
     tenant = NestedTenantSerializer()
     status = ChoiceFieldSerializer(choices=VLAN_STATUS_CHOICES)
     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_field_values',
+            'custom_fields',
         ]
 
 
@@ -172,20 +169,19 @@ class WritableVLANSerializer(serializers.ModelSerializer):
 # Prefixes
 #
 
-class PrefixSerializer(serializers.ModelSerializer):
+class PrefixSerializer(CustomFieldModelSerializer):
     site = NestedSiteSerializer()
     vrf = NestedVRFSerializer()
     tenant = NestedTenantSerializer()
     vlan = NestedVLANSerializer()
     status = ChoiceFieldSerializer(choices=PREFIX_STATUS_CHOICES)
     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_field_values',
+            'custom_fields',
         ]
 
 
@@ -210,18 +206,17 @@ class WritablePrefixSerializer(serializers.ModelSerializer):
 # IP addresses
 #
 
-class IPAddressSerializer(serializers.ModelSerializer):
+class IPAddressSerializer(CustomFieldModelSerializer):
     vrf = NestedVRFSerializer()
     tenant = NestedTenantSerializer()
     status = ChoiceFieldSerializer(choices=IPADDRESS_STATUS_CHOICES)
     interface = InterfaceSerializer()
-    custom_field_values = CustomFieldValueSerializer(many=True)
 
     class Meta:
         model = IPAddress
         fields = [
             'id', 'family', 'address', 'vrf', 'tenant', 'status', 'interface', 'description', 'nat_inside',
-            'nat_outside', 'custom_field_values',
+            'nat_outside', 'custom_fields',
         ]
 
 

+ 3 - 4
netbox/tenancy/api/serializers.py

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 
-from extras.api.serializers import CustomFieldValueSerializer
+from extras.api.serializers import CustomFieldModelSerializer
 from tenancy.models import Tenant, TenantGroup
 
 
@@ -27,13 +27,12 @@ class NestedTenantGroupSerializer(serializers.ModelSerializer):
 # Tenants
 #
 
-class TenantSerializer(serializers.ModelSerializer):
+class TenantSerializer(CustomFieldModelSerializer):
     group = NestedTenantGroupSerializer()
-    custom_field_values = CustomFieldValueSerializer(many=True)
 
     class Meta:
         model = Tenant
-        fields = ['id', 'name', 'slug', 'group', 'description', 'comments', 'custom_field_values']
+        fields = ['id', 'name', 'slug', 'group', 'description', 'comments', 'custom_fields']
 
 
 class NestedTenantSerializer(serializers.ModelSerializer):