瀏覽代碼

Fixes #19918: Resolve {module} placeholders in nested module bay labels

ModuleBayTemplate.instantiate() now calls resolve_name() and resolve_label()
to properly resolve {module} placeholders, making it consistent with other
modular components like InterfaceTemplate.

When a module with nested module bays is installed (e.g., a module with SFP
bays in position "A"), the nested bay labels now correctly show "A-21" instead
of "{module}-21".

This also removes the inconsistent fix from #17436 which only handled name
resolution post-instantiation. The proper resolution now happens during
instantiation using the existing resolve methods.
Jason Novinger 2 月之前
父節點
當前提交
269112a565
共有 3 個文件被更改,包括 50 次插入6 次删除
  1. 2 2
      netbox/dcim/models/device_component_templates.py
  2. 0 2
      netbox/dcim/models/modules.py
  3. 48 2
      netbox/dcim/tests/test_models.py

+ 2 - 2
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
         )

+ 0 - 2
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']

+ 48 - 2
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):