Преглед изворни кода

Clean up UniqueTogetherValidator workarounds

jeremystretch пре 4 година
родитељ
комит
8d0ed99bcd
2 измењених фајлова са 12 додато и 66 уклоњено
  1. 8 36
      netbox/dcim/api/serializers.py
  2. 4 30
      netbox/ipam/api/serializers.py

+ 8 - 36
netbox/dcim/api/serializers.py

@@ -2,7 +2,6 @@ from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from drf_yasg.utils import swagger_serializer_method
 from drf_yasg.utils import swagger_serializer_method
 from rest_framework import serializers
 from rest_framework import serializers
-from rest_framework.validators import UniqueTogetherValidator
 from timezone_field.rest_framework import TimeZoneSerializerField
 from timezone_field.rest_framework import TimeZoneSerializerField
 
 
 from dcim.choices import *
 from dcim.choices import *
@@ -170,6 +169,8 @@ class RackSerializer(PrimaryModelSerializer):
     status = ChoiceField(choices=RackStatusChoices, required=False)
     status = ChoiceField(choices=RackStatusChoices, required=False)
     role = NestedRackRoleSerializer(required=False, allow_null=True)
     role = NestedRackRoleSerializer(required=False, allow_null=True)
     type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
     type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
+    facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label='Facility ID',
+                                        default=None)
     width = ChoiceField(choices=RackWidthChoices, required=False)
     width = ChoiceField(choices=RackWidthChoices, required=False)
     outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
     outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
     device_count = serializers.IntegerField(read_only=True)
     device_count = serializers.IntegerField(read_only=True)
@@ -182,23 +183,6 @@ class RackSerializer(PrimaryModelSerializer):
             'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
             'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
             'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count',
             'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count',
         ]
         ]
-        # Omit the UniqueTogetherValidator that would be automatically added to validate (location, facility_id). This
-        # prevents facility_id from being interpreted as a required field.
-        validators = [
-            UniqueTogetherValidator(queryset=Rack.objects.all(), fields=('location', 'name'))
-        ]
-
-    def validate(self, data):
-
-        # Validate uniqueness of (location, facility_id) since we omitted the automatically-created validator from Meta.
-        if data.get('facility_id', None):
-            validator = UniqueTogetherValidator(queryset=Rack.objects.all(), fields=('location', 'facility_id'))
-            validator(data, self)
-
-        # Enforce model validation
-        super().validate(data)
-
-        return data
 
 
 
 
 class RackUnitSerializer(serializers.Serializer):
 class RackUnitSerializer(serializers.Serializer):
@@ -458,12 +442,13 @@ class DeviceSerializer(PrimaryModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
     device_type = NestedDeviceTypeSerializer()
     device_type = NestedDeviceTypeSerializer()
     device_role = NestedDeviceRoleSerializer()
     device_role = NestedDeviceRoleSerializer()
-    tenant = NestedTenantSerializer(required=False, allow_null=True)
+    tenant = NestedTenantSerializer(required=False, allow_null=True, default=None)
     platform = NestedPlatformSerializer(required=False, allow_null=True)
     platform = NestedPlatformSerializer(required=False, allow_null=True)
     site = NestedSiteSerializer()
     site = NestedSiteSerializer()
     location = NestedLocationSerializer(required=False, allow_null=True, default=None)
     location = NestedLocationSerializer(required=False, allow_null=True, default=None)
-    rack = NestedRackSerializer(required=False, allow_null=True)
-    face = ChoiceField(choices=DeviceFaceChoices, allow_blank=True, required=False)
+    rack = NestedRackSerializer(required=False, allow_null=True, default=None)
+    face = ChoiceField(choices=DeviceFaceChoices, allow_blank=True, default='')
+    position = serializers.IntegerField(allow_null=True, label='Position (U)', min_value=1, default=None)
     status = ChoiceField(choices=DeviceStatusChoices, required=False)
     status = ChoiceField(choices=DeviceStatusChoices, required=False)
     airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
     airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
     primary_ip = NestedIPAddressSerializer(read_only=True)
     primary_ip = NestedIPAddressSerializer(read_only=True)
@@ -471,7 +456,8 @@ class DeviceSerializer(PrimaryModelSerializer):
     primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
     primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
     parent_device = serializers.SerializerMethodField()
     parent_device = serializers.SerializerMethodField()
     cluster = NestedClusterSerializer(required=False, allow_null=True)
     cluster = NestedClusterSerializer(required=False, allow_null=True)
-    virtual_chassis = NestedVirtualChassisSerializer(required=False, allow_null=True)
+    virtual_chassis = NestedVirtualChassisSerializer(required=False, allow_null=True, default=None)
+    vc_position = serializers.IntegerField(allow_null=True, max_value=255, min_value=0, default=None)
 
 
     class Meta:
     class Meta:
         model = Device
         model = Device
@@ -481,19 +467,6 @@ class DeviceSerializer(PrimaryModelSerializer):
             'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments',
             'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments',
             'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
             'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
         ]
         ]
-        validators = []
-
-    def validate(self, data):
-
-        # Validate uniqueness of (rack, position, face) since we omitted the automatically-created validator from Meta.
-        if data.get('rack') and data.get('position') and data.get('face'):
-            validator = UniqueTogetherValidator(queryset=Device.objects.all(), fields=('rack', 'position', 'face'))
-            validator(data, self)
-
-        # Enforce model validation
-        super().validate(data)
-
-        return data
 
 
     @swagger_serializer_method(serializer_or_field=NestedDeviceSerializer)
     @swagger_serializer_method(serializer_or_field=NestedDeviceSerializer)
     def get_parent_device(self, obj):
     def get_parent_device(self, obj):
@@ -730,7 +703,6 @@ class DeviceBaySerializer(PrimaryModelSerializer):
 class InventoryItemSerializer(PrimaryModelSerializer):
 class InventoryItemSerializer(PrimaryModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail')
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail')
     device = NestedDeviceSerializer()
     device = NestedDeviceSerializer()
-    # Provide a default value to satisfy UniqueTogetherValidator
     parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None)
     parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None)
     manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None)
     manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None)
     _depth = serializers.IntegerField(source='level', read_only=True)
     _depth = serializers.IntegerField(source='level', read_only=True)

+ 4 - 30
netbox/ipam/api/serializers.py

@@ -3,7 +3,6 @@ from collections import OrderedDict
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from drf_yasg.utils import swagger_serializer_method
 from drf_yasg.utils import swagger_serializer_method
 from rest_framework import serializers
 from rest_framework import serializers
-from rest_framework.validators import UniqueTogetherValidator
 
 
 from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
 from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
 from ipam.choices import *
 from ipam.choices import *
@@ -117,8 +116,10 @@ class VLANGroupSerializer(OrganizationalModelSerializer):
         queryset=ContentType.objects.filter(
         queryset=ContentType.objects.filter(
             model__in=VLANGROUP_SCOPE_TYPES
             model__in=VLANGROUP_SCOPE_TYPES
         ),
         ),
-        required=False
+        required=False,
+        default=None
     )
     )
+    scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
     scope = serializers.SerializerMethodField(read_only=True)
     scope = serializers.SerializerMethodField(read_only=True)
     vlan_count = serializers.IntegerField(read_only=True)
     vlan_count = serializers.IntegerField(read_only=True)
 
 
@@ -130,19 +131,6 @@ class VLANGroupSerializer(OrganizationalModelSerializer):
         ]
         ]
         validators = []
         validators = []
 
 
-    def validate(self, data):
-
-        # Validate uniqueness of name and slug if a site has been assigned.
-        if data.get('site', None):
-            for field in ['name', 'slug']:
-                validator = UniqueTogetherValidator(queryset=VLANGroup.objects.all(), fields=('site', field))
-                validator(data, self)
-
-        # Enforce model validation
-        super().validate(data)
-
-        return data
-
     def get_scope(self, obj):
     def get_scope(self, obj):
         if obj.scope_id is None:
         if obj.scope_id is None:
             return None
             return None
@@ -155,7 +143,7 @@ class VLANGroupSerializer(OrganizationalModelSerializer):
 class VLANSerializer(PrimaryModelSerializer):
 class VLANSerializer(PrimaryModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
     url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
     site = NestedSiteSerializer(required=False, allow_null=True)
     site = NestedSiteSerializer(required=False, allow_null=True)
-    group = NestedVLANGroupSerializer(required=False, allow_null=True)
+    group = NestedVLANGroupSerializer(required=False, allow_null=True, default=None)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
     status = ChoiceField(choices=VLANStatusChoices, required=False)
     status = ChoiceField(choices=VLANStatusChoices, required=False)
     role = NestedRoleSerializer(required=False, allow_null=True)
     role = NestedRoleSerializer(required=False, allow_null=True)
@@ -167,20 +155,6 @@ class VLANSerializer(PrimaryModelSerializer):
             'id', 'url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'tags',
             'id', 'url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'tags',
             'custom_fields', 'created', 'last_updated', 'prefix_count',
             'custom_fields', 'created', 'last_updated', 'prefix_count',
         ]
         ]
-        validators = []
-
-    def validate(self, data):
-
-        # Validate uniqueness of vid and name if a group has been assigned.
-        if data.get('group', None):
-            for field in ['vid', 'name']:
-                validator = UniqueTogetherValidator(queryset=VLAN.objects.all(), fields=('group', field))
-                validator(data, self)
-
-        # Enforce model validation
-        super().validate(data)
-
-        return data
 
 
 
 
 #
 #