Coverage for extras/api/serializers_/customfields.py: 58%

52 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django.utils.translation import gettext as _ 

2from drf_spectacular.types import OpenApiTypes 

3from drf_spectacular.utils import extend_schema_field 

4from rest_framework import serializers 

5 

6from core.models import ObjectType 

7from extras.choices import * 

8from extras.models import CustomField, CustomFieldChoiceSet 

9from netbox.api.fields import ChoiceField, ContentTypeField 

10from netbox.api.serializers import ChangeLogMessageSerializer, ValidatedModelSerializer 

11from users.api.serializers_.mixins import OwnerMixin 

12 

13__all__ = ( 

14 'CustomFieldChoiceSetSerializer', 

15 'CustomFieldSerializer', 

16) 

17 

18 

19class CustomFieldChoiceSetSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer): 

20 base_choices = ChoiceField( 

21 choices=CustomFieldChoiceSetBaseChoices, 

22 required=False, 

23 allow_null=True, 

24 ) 

25 extra_choices = serializers.ListField( 

26 child=serializers.ListField( 

27 min_length=2, 

28 max_length=2 

29 ) 

30 ) 

31 choice_colors = serializers.DictField( 

32 child=serializers.ChoiceField(choices=CustomFieldChoiceColorChoices), 

33 required=False, 

34 ) 

35 choices_count = serializers.IntegerField(read_only=True) 

36 

37 class Meta: 

38 model = CustomFieldChoiceSet 

39 fields = [ 

40 'id', 'url', 'display_url', 'display', 'name', 'description', 'base_choices', 'extra_choices', 

41 'choice_colors', 'order_alphabetically', 'choices_count', 'owner', 'created', 'last_updated', 

42 ] 

43 brief_fields = ('id', 'url', 'display', 'name', 'description', 'choices_count') 

44 

45 

46class CustomFieldSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedModelSerializer): 

47 object_types = ContentTypeField( 

48 queryset=ObjectType.objects.with_feature('custom_fields'), 

49 many=True 

50 ) 

51 type = ChoiceField(choices=CustomFieldTypeChoices) 

52 related_object_type = ContentTypeField( 

53 queryset=ObjectType.objects.all(), 

54 required=False, 

55 allow_null=True 

56 ) 

57 filter_logic = ChoiceField(choices=CustomFieldFilterLogicChoices, required=False) 

58 data_type = serializers.SerializerMethodField() 

59 choice_set = CustomFieldChoiceSetSerializer( 

60 nested=True, 

61 required=False, 

62 allow_null=True 

63 ) 

64 ui_visible = ChoiceField(choices=CustomFieldUIVisibleChoices, required=False) 

65 ui_editable = ChoiceField(choices=CustomFieldUIEditableChoices, required=False) 

66 # A field is live only while active; the remaining states report a pending bulk update of its 

67 # stored data. Read-only: the state is driven by the responsible background job. 

68 status = ChoiceField(choices=CustomFieldStatusChoices, read_only=True) 

69 

70 class Meta: 

71 model = CustomField 

72 fields = [ 

73 'id', 'url', 'display_url', 'display', 'object_types', 'type', 'related_object_type', 'data_type', 

74 'name', 'label', 'group_name', 'description', 'required', 'unique', 'search_weight', 'filter_logic', 

75 'ui_visible', 'ui_editable', 'is_cloneable', 'nulls_first', 'default', 'related_object_filter', 'weight', 

76 'validation_minimum', 'validation_maximum', 'validation_regex', 'validation_schema', 'choice_set', 

77 'status', 'owner', 'comments', 'created', 'last_updated', 

78 ] 

79 brief_fields = ('id', 'url', 'display', 'name', 'description') 

80 

81 def validate_type(self, value): 

82 if self.instance and self.instance.type != value: 

83 raise serializers.ValidationError(_('Changing the type of custom fields is not supported.')) 

84 

85 return value 

86 

87 @extend_schema_field(OpenApiTypes.STR) 

88 def get_data_type(self, obj): 

89 types = CustomFieldTypeChoices 

90 if obj.type == types.TYPE_INTEGER: 

91 return 'integer' 

92 if obj.type == types.TYPE_DECIMAL: 

93 return 'decimal' 

94 if obj.type == types.TYPE_BOOLEAN: 

95 return 'boolean' 

96 if obj.type in (types.TYPE_JSON, types.TYPE_OBJECT): 

97 return 'object' 

98 if obj.type in (types.TYPE_MULTISELECT, types.TYPE_MULTIOBJECT): 

99 return 'array' 

100 return 'string'