Просмотр исходного кода

FieldChoicesViewSet should infer field choices from serializer, not model

Jeremy Stretch 7 лет назад
Родитель
Сommit
fc76c8eb0f

+ 7 - 2
netbox/dcim/api/serializers.py

@@ -1,3 +1,4 @@
+from django.contrib.contenttypes.models import ContentType
 from rest_framework import serializers
 from rest_framework.validators import UniqueTogetherValidator
 from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
@@ -502,8 +503,12 @@ class InventoryItemSerializer(TaggitSerializer, ValidatedModelSerializer):
 #
 
 class CableSerializer(ValidatedModelSerializer):
-    termination_a_type = ContentTypeField()
-    termination_b_type = ContentTypeField()
+    termination_a_type = ContentTypeField(
+        queryset=ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
+    )
+    termination_b_type = ContentTypeField(
+        queryset=ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
+    )
     termination_a = serializers.SerializerMethodField(read_only=True)
     termination_b = serializers.SerializerMethodField(read_only=True)
     status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, required=False)

+ 1 - 1
netbox/dcim/api/views.py

@@ -1,7 +1,7 @@
 from collections import OrderedDict
 
 from django.conf import settings
-from django.db.models import F, Q
+from django.db.models import F
 from django.http import HttpResponseForbidden
 from django.shortcuts import get_object_or_404
 from drf_yasg import openapi

+ 4 - 1
netbox/extras/api/serializers.py

@@ -1,3 +1,4 @@
+from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist
 from rest_framework import serializers
 from taggit.models import Tag
@@ -88,7 +89,9 @@ class TagSerializer(ValidatedModelSerializer):
 #
 
 class ImageAttachmentSerializer(ValidatedModelSerializer):
-    content_type = ContentTypeField()
+    content_type = ContentTypeField(
+        queryset=ContentType.objects.all()
+    )
     parent = serializers.SerializerMethodField(read_only=True)
 
     class Meta:

+ 0 - 1
netbox/extras/api/views.py

@@ -23,7 +23,6 @@ from . import serializers
 
 class ExtrasFieldChoicesViewSet(FieldChoicesViewSet):
     fields = (
-        (CustomField, ['type']),
         (Graph, ['type']),
     )
 

+ 2 - 0
netbox/ipam/api/serializers.py

@@ -128,6 +128,7 @@ class VLANSerializer(TaggitSerializer, CustomFieldModelSerializer):
 #
 
 class PrefixSerializer(TaggitSerializer, CustomFieldModelSerializer):
+    family = ChoiceField(choices=AF_CHOICES, read_only=True)
     site = NestedSiteSerializer(required=False, allow_null=True)
     vrf = NestedVRFSerializer(required=False, allow_null=True)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
@@ -189,6 +190,7 @@ class IPAddressInterfaceSerializer(WritableNestedSerializer):
 
 
 class IPAddressSerializer(TaggitSerializer, CustomFieldModelSerializer):
+    family = ChoiceField(choices=AF_CHOICES, read_only=True)
     vrf = NestedVRFSerializer(required=False, allow_null=True)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
     status = ChoiceField(choices=IPADDRESS_STATUS_CHOICES, required=False)

+ 12 - 6
netbox/utilities/api.py

@@ -32,7 +32,9 @@ def get_serializer_for_model(model, prefix=''):
     try:
         return dynamic_import(serializer_name)
     except AttributeError:
-        return None
+        raise Exception(
+            "Could not determine serializer for {}.{} with prefix '{}'".format(app_name, model_name, prefix)
+        )
 
 
 #
@@ -100,6 +102,10 @@ class ChoiceField(Field):
 
         return data
 
+    @property
+    def choices(self):
+        return self._choices
+
 
 class ContentTypeField(RelatedField):
     """
@@ -110,10 +116,6 @@ class ContentTypeField(RelatedField):
         "invalid": "Invalid value. Specify a content type as '<app_label>.<model_name>'.",
     }
 
-    # Can't set this as an attribute because it raises an exception when the field is read-only
-    def get_queryset(self):
-        return ContentType.objects.all()
-
     def to_internal_value(self, data):
         try:
             app_label, model = data.split('.')
@@ -256,10 +258,14 @@ class FieldChoicesViewSet(ViewSet):
         self._fields = OrderedDict()
         for cls, field_list in self.fields:
             for field_name in field_list:
+
                 model_name = cls._meta.verbose_name.lower().replace(' ', '-')
                 key = ':'.join([model_name, field_name])
+
+                serializer = get_serializer_for_model(cls)()
                 choices = []
-                for k, v in cls._meta.get_field(field_name).choices:
+
+                for k, v in serializer.get_fields()[field_name].choices.items():
                     if type(v) in [list, tuple]:
                         for k2, v2 in v:
                             choices.append({