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

Fixes #22802: Align the available-prefixes request serializer with the endpoint's actual behavior

Address review feedback on the schema serializer. Drop the `vrf` field:
prep_object_data always assigns the parent prefix's VRF, so advertising it
as writable was misleading (same reason `prefix` is omitted). Change the base
class from NetBoxModelSerializer to PrimaryModelSerializer so the `owner` field
renders as the nested OwnerSerializer form, matching PrefixSerializer rather
than a bare integer. Add a regression test confirming a caller-supplied VRF is
ignored in favor of the parent's.
Jason Novinger 2 дней назад
Родитель
Сommit
0c248ef79c
2 измененных файлов с 22 добавлено и 7 удалено
  1. 7 7
      netbox/ipam/api/serializers_/ip.py
  2. 15 0
      netbox/ipam/tests/test_api.py

+ 7 - 7
netbox/ipam/api/serializers_/ip.py

@@ -7,7 +7,7 @@ from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
 from ipam.models import Aggregate, IPAddress, IPRange, Prefix
 from netbox.api.fields import ChoiceField, ContentTypeField
 from netbox.api.gfk_fields import GFKSerializerField
-from netbox.api.serializers import NetBoxModelSerializer, PrimaryModelSerializer
+from netbox.api.serializers import PrimaryModelSerializer
 from tenancy.api.serializers_.tenants import TenantSerializer
 
 from ..field_serializers import IPAddressField, IPNetworkField
@@ -103,14 +103,14 @@ class PrefixLengthSerializer(serializers.Serializer):
         return data
 
 
-class CreateAvailablePrefixSerializer(NetBoxModelSerializer):
+class CreateAvailablePrefixSerializer(PrimaryModelSerializer):
     """
-    Request payload for creating prefixes from the available-prefixes endpoint. The parent prefix supplies the
-    `prefix` value (via a requested `prefix_length`), so `prefix` is omitted here. The writable fields mirror
-    those of PrefixSerializer (minus read-only/computed fields); keep them in sync if PrefixSerializer changes.
+    Request payload for creating prefixes from the available-prefixes endpoint. The parent prefix supplies both
+    the `prefix` value (via a requested `prefix_length`) and the `vrf`, so neither is accepted here. The remaining
+    writable fields mirror those of PrefixSerializer (minus read-only/computed fields); keep them in sync if
+    PrefixSerializer changes.
     """
     prefix_length = serializers.IntegerField()
-    vrf = VRFSerializer(nested=True, required=False, allow_null=True)
     scope_type = ContentTypeField(
         queryset=ContentType.objects.filter(
             model__in=LOCATION_SCOPE_TYPES
@@ -128,7 +128,7 @@ class CreateAvailablePrefixSerializer(NetBoxModelSerializer):
     class Meta:
         model = Prefix
         fields = [
-            'prefix_length', 'vrf', 'scope_type', 'scope_id', 'tenant', 'vlan', 'status', 'role', 'is_pool',
+            'prefix_length', 'scope_type', 'scope_id', 'tenant', 'vlan', 'status', 'role', 'is_pool',
             'mark_utilized', 'description', 'owner', 'comments', 'tags', 'custom_fields',
         ]
 

+ 15 - 0
netbox/ipam/tests/test_api.py

@@ -542,6 +542,21 @@ class PrefixTestCase(APIViewTestCases.APIViewTestCase):
         self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
         self.assertIn('prefix_length', response.data[0])
 
+    def test_create_available_prefix_inherits_parent_vrf(self):
+        """
+        A caller-supplied VRF is ignored: a prefix created from the available-prefixes endpoint always inherits
+        the parent prefix's VRF. This is why `vrf` is not advertised as a writable field on the request.
+        """
+        parent_vrf = VRF.objects.create(name='VRF 1')
+        other_vrf = VRF.objects.create(name='VRF 2')
+        prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/28'), vrf=parent_vrf, is_pool=True)
+        url = reverse('ipam-api:prefix-available-prefixes', kwargs={'pk': prefix.pk})
+        self.add_permissions('ipam.view_prefix', 'ipam.add_prefix')
+
+        response = self.client.post(url, {'prefix_length': 30, 'vrf': other_vrf.pk}, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_201_CREATED)
+        self.assertEqual(response.data['vrf']['id'], parent_vrf.pk)
+
     def test_create_multiple_available_prefixes(self):
         """
         Test the creation of available prefixes within a parent prefix.