diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index f8f2e100f..6eea97743 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -681,8 +681,8 @@ class ModuleBayTemplate(ModularComponentTemplateModel): def instantiate(self, **kwargs): return self.component_model( - name=self.name, - label=self.label, + name=self.resolve_name(kwargs.get('module')), + label=self.resolve_label(kwargs.get('module')), position=self.position, **kwargs ) diff --git a/netbox/dcim/models/modules.py b/netbox/dcim/models/modules.py index 4376f40aa..1c3f9f730 100644 --- a/netbox/dcim/models/modules.py +++ b/netbox/dcim/models/modules.py @@ -7,7 +7,6 @@ from django.utils.translation import gettext_lazy as _ from jsonschema.exceptions import ValidationError as JSONValidationError from dcim.choices import * -from dcim.constants import MODULE_TOKEN from dcim.utils import update_interface_bridges from extras.models import ConfigContextModel, CustomField from netbox.models import PrimaryModel @@ -331,7 +330,6 @@ class Module(PrimaryModel, ConfigContextModel): else: # ModuleBays must be saved individually for MPTT for instance in create_instances: - instance.name = instance.name.replace(MODULE_TOKEN, str(self.module_bay.position)) instance.save() update_fields = ['module'] diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index 877af600b..e67f32e60 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -792,8 +792,54 @@ class ModuleBayTestCase(TestCase): ) device.consoleports.first() - def test_nested_module_token(self): - pass + @tag('regression') # #19918 + def test_nested_module_bay_label_resolution(self): + """Test that nested module bay labels properly resolve {module} placeholders""" + manufacturer = Manufacturer.objects.first() + site = Site.objects.first() + device_role = DeviceRole.objects.first() + + # Create device type with module bay template (position='A') + device_type = DeviceType.objects.create( + manufacturer=manufacturer, + model='Device with Bays', + slug='device-with-bays' + ) + ModuleBayTemplate.objects.create( + device_type=device_type, + name='Bay A', + position='A' + ) + + # Create module type with nested bay template using {module} placeholder + module_type = ModuleType.objects.create( + manufacturer=manufacturer, + model='Module with Nested Bays' + ) + ModuleBayTemplate.objects.create( + module_type=module_type, + name='SFP {module}-21', + label='{module}-21', + position='21' + ) + + # Create device and install module + device = Device.objects.create( + name='Test Device', + device_type=device_type, + role=device_role, + site=site + ) + module_bay = device.modulebays.get(name='Bay A') + module = Module.objects.create( + device=device, + module_bay=module_bay, + module_type=module_type + ) + + # Verify nested bay label resolves {module} to parent position + nested_bay = module.modulebays.get(name='SFP A-21') + self.assertEqual(nested_bay.label, 'A-21') class CableTestCase(TestCase):