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

fix(circuits): Add custom fields support to CircuitGroupAssignment

Adds custom_fields to CircuitGroupAssignmentSerializer fields list and
CustomFieldsMixin to CircuitGroupAssignmentType. Includes regression
tests for REST API updates and GraphQL queries.

Fixes #23369
Martin Hauser 1 день назад
Родитель
Сommit
932078d24c

+ 1 - 1
netbox/circuits/api/serializers_/circuits.py

@@ -158,7 +158,7 @@ class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_):
         model = CircuitGroupAssignment
         fields = [
             'id', 'url', 'display_url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority', 'tags',
-            'created', 'last_updated',
+            'custom_fields', 'created', 'last_updated',
         ]
         brief_fields = ('id', 'url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority')
 

+ 1 - 1
netbox/circuits/graphql/types.py

@@ -144,7 +144,7 @@ class CircuitGroupType(OrganizationalObjectType):
     filters=CircuitGroupAssignmentFilter,
     pagination=True
 )
-class CircuitGroupAssignmentType(TagsMixin, BaseObjectType):
+class CircuitGroupAssignmentType(CustomFieldsMixin, TagsMixin, BaseObjectType):
     group: Annotated['CircuitGroupType', strawberry.lazy('circuits.graphql.types')]
 
     @strawberry_django.field(

+ 37 - 0
netbox/circuits/tests/test_api.py

@@ -4,8 +4,11 @@ from rest_framework import status
 
 from circuits.choices import *
 from circuits.models import *
+from core.models import ObjectType
 from dcim.choices import InterfaceTypeChoices
 from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
+from extras.choices import CustomFieldTypeChoices
+from extras.models import CustomField
 from ipam.models import ASN, RIR
 from utilities.testing import APITestCase, APIViewTestCases
 
@@ -463,6 +466,40 @@ class CircuitGroupAssignmentTestCase(APIViewTestCases.APIViewTestCase):
             },
         ]
 
+    @tag('regression')  # Ref: #23369
+    def test_update_custom_fields(self):
+        """Custom field data sent when updating an assignment is saved and rendered."""
+        custom_field = CustomField.objects.create(name='cf1', type=CustomFieldTypeChoices.TYPE_TEXT)
+        custom_field.object_types.set([ObjectType.objects.get_for_model(CircuitGroupAssignment)])
+        self.add_permissions('circuits.change_circuitgroupassignment')
+        assignment = CircuitGroupAssignment.objects.first()
+        data = {
+            'custom_fields': {'cf1': 'foo'},
+        }
+
+        response = self.client.patch(self._get_detail_url(assignment), data, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertIn('custom_fields', response.data)
+        self.assertEqual(response.data['custom_fields'], {'cf1': 'foo'})
+        assignment.refresh_from_db()
+        self.assertEqual(assignment.custom_field_data, {'cf1': 'foo'})
+
+    @tag('regression')  # Ref: #23369
+    def test_graphql_custom_fields(self):
+        """The GraphQL type renders the custom field data of an assignment."""
+        custom_field = CustomField.objects.create(name='cf1', type=CustomFieldTypeChoices.TYPE_TEXT)
+        custom_field.object_types.set([ObjectType.objects.get_for_model(CircuitGroupAssignment)])
+        self.add_permissions('circuits.view_circuitgroupassignment')
+        assignment = CircuitGroupAssignment.objects.first()
+        CircuitGroupAssignment.objects.filter(pk=assignment.pk).update(custom_field_data={'cf1': 'foo'})
+
+        query = '{ circuit_group_assignment(id: ' + str(assignment.pk) + ') { custom_fields } }'
+        response = self.client.post(reverse('graphql'), data={'query': query}, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        data = response.json()
+        self.assertNotIn('errors', data)
+        self.assertEqual(data['data']['circuit_group_assignment']['custom_fields'], {'cf1': 'foo'})
+
 
 class ProviderNetworkTestCase(APIViewTestCases.APIViewTestCase):
     model = ProviderNetwork