feat(ipam): Add standard fields to VLAN Translation serializers

Add display_url, tags, custom_fields, created, and last_updated fields
to VLANTranslationPolicy and VLANTranslationRule serializers. Configure
nested rules to use brief representation and update API tests to verify
tag assignment and standard field presence.

Fixes #23125
This commit is contained in:
Martin Hauser 2026-09-08 19:31:05 +02:00
parent 7b56158d47
commit 903e4505aa
No known key found for this signature in database
3 changed files with 69 additions and 6 deletions

View File

@ -117,13 +117,20 @@ class VLANTranslationRuleSerializer(NetBoxModelSerializer):
class Meta:
model = VLANTranslationRule
fields = ['id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description']
fields = [
'id', 'url', 'display_url', 'display', 'policy', 'local_vid', 'remote_vid', 'description', 'tags',
'custom_fields', 'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description')
class VLANTranslationPolicySerializer(PrimaryModelSerializer):
rules = VLANTranslationRuleSerializer(many=True, read_only=True)
rules = VLANTranslationRuleSerializer(nested=True, many=True, read_only=True)
class Meta:
model = VLANTranslationPolicy
fields = ['id', 'url', 'display', 'name', 'description', 'display', 'rules', 'owner', 'comments']
fields = [
'id', 'url', 'display_url', 'display', 'name', 'description', 'rules', 'owner', 'comments', 'tags',
'custom_fields', 'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'name', 'description')

View File

@ -28,9 +28,9 @@
"vlan:list_objects_with_permission": 21,
"vlangroup:api_list_objects": 12,
"vlangroup:list_objects_with_permission": 22,
"vlantranslationpolicy:api_list_objects": 12,
"vlantranslationpolicy:api_list_objects": 13,
"vlantranslationpolicy:list_objects_with_permission": 17,
"vlantranslationrule:api_list_objects": 12,
"vlantranslationrule:api_list_objects": 13,
"vlantranslationrule:list_objects_with_permission": 18,
"vrf:api_list_objects": 20,
"vrf:list_objects_with_permission": 17

View File

@ -11,7 +11,7 @@ from ipam.choices import *
from ipam.models import *
from tenancy.models import Tenant
from utilities.data import string_to_ranges
from utilities.testing import APITestCase, APIViewTestCases, create_test_device, disable_logging
from utilities.testing import APITestCase, APIViewTestCases, create_tags, create_test_device, disable_logging
class AppTestCase(APITestCase):
@ -1422,6 +1422,39 @@ class VLANTranslationPolicyTestCase(APIViewTestCases.APIViewTestCase):
},
]
def test_standard_fields_in_representation(self):
"""The standard URL, tag, custom-field and change-tracking names appear in the representation."""
policy = VLANTranslationPolicy.objects.first()
self.add_permissions('ipam.view_vlantranslationpolicy')
response = self.client.get(self._get_detail_url(policy), **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
expected = {'display_url', 'tags', 'custom_fields', 'created', 'last_updated'}
self.assertEqual(expected - set(response.data), set())
def test_nested_rules_are_brief(self):
"""Rules nested in a policy representation carry only the rule serializer's brief fields."""
policy = VLANTranslationPolicy.objects.first()
VLANTranslationRule.objects.create(policy=policy, local_vid=100, remote_vid=200)
self.add_permissions('ipam.view_vlantranslationpolicy')
response = self.client.get(self._get_detail_url(policy), **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(sorted(response.data['rules'][0]), VLANTranslationRuleTestCase.brief_fields)
def test_update_tags(self):
"""Tags supplied on update are assigned and rendered in the response."""
policy = VLANTranslationPolicy.objects.first()
create_tags('Alpha')
self.add_permissions('ipam.change_vlantranslationpolicy', 'extras.view_tag')
data = {'tags': [{'slug': 'alpha'}]}
response = self.client.patch(self._get_detail_url(policy), data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertIn('tags', response.data)
self.assertEqual([tag['slug'] for tag in response.data['tags']], ['alpha'])
self.assertEqual(list(policy.tags.values_list('slug', flat=True)), ['alpha'])
class VLANTranslationRuleTestCase(APIViewTestCases.APIViewTestCase):
model = VLANTranslationRule
@ -1491,6 +1524,29 @@ class VLANTranslationRuleTestCase(APIViewTestCases.APIViewTestCase):
'description': 'New description',
}
def test_standard_fields_in_representation(self):
"""The standard URL, tag, custom-field and change-tracking names appear in the representation."""
rule = VLANTranslationRule.objects.first()
self.add_permissions('ipam.view_vlantranslationrule')
response = self.client.get(self._get_detail_url(rule), **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
expected = {'display_url', 'tags', 'custom_fields', 'created', 'last_updated'}
self.assertEqual(expected - set(response.data), set())
def test_update_tags(self):
"""Tags supplied on update are assigned and rendered in the response."""
rule = VLANTranslationRule.objects.first()
create_tags('Alpha')
self.add_permissions('ipam.change_vlantranslationrule', 'extras.view_tag')
data = {'tags': [{'slug': 'alpha'}]}
response = self.client.patch(self._get_detail_url(rule), data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertIn('tags', response.data)
self.assertEqual([tag['slug'] for tag in response.data['tags']], ['alpha'])
self.assertEqual(list(rule.tags.values_list('slug', flat=True)), ['alpha'])
class ServiceTemplateTestCase(APIViewTestCases.APIViewTestCase):
model = ServiceTemplate