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

fixes #5314 - Fix config context rendering when multiple tags are assgined to an object

John Anderson 5 лет назад
Родитель
Сommit
0d27abc6fc

+ 1 - 0
docs/release-notes/version-2.9.md

@@ -10,6 +10,7 @@
 ### Bug Fixes
 
 * [#5271](https://github.com/netbox-community/netbox/issues/5271) - Fix auto-population of region field when editing a device
+* [#5314](https://github.com/netbox-community/netbox/issues/5314) - Fix config context rendering when multiple tags are assgined to an object
 
 
 ---

+ 2 - 2
netbox/extras/querysets.py

@@ -60,7 +60,7 @@ class ConfigContextQuerySet(RestrictedQuerySet):
             Q(tenants=obj.tenant) | Q(tenants=None),
             Q(tags__slug__in=obj.tags.slugs()) | Q(tags=None),
             is_active=True,
-        ).order_by('weight', 'name')
+        ).order_by('weight', 'name').distinct()
 
         if aggregate_data:
             return queryset.aggregate(
@@ -95,7 +95,7 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
                     _data=EmptyGroupByJSONBAgg('data', ordering=['weight', 'name'])
                 ).values("_data")
             )
-        )
+        ).distinct()
 
     def _get_config_context_filters(self):
         # Construct the set of Q objects for the specific object types

+ 35 - 0
netbox/extras/tests/test_models.py

@@ -75,6 +75,7 @@ class ConfigContextTest(TestCase):
         self.tenantgroup = TenantGroup.objects.create(name="Tenant Group")
         self.tenant = Tenant.objects.create(name="Tenant", group=self.tenantgroup)
         self.tag = Tag.objects.create(name="Tag", slug="tag")
+        self.tag2 = Tag.objects.create(name="Tag2", slug="tag2")
 
         self.device = Device.objects.create(
             name='Device 1',
@@ -328,3 +329,37 @@ class ConfigContextTest(TestCase):
 
         annotated_queryset = VirtualMachine.objects.filter(name=virtual_machine.name).annotate_config_context_data()
         self.assertEqual(virtual_machine.get_config_context(), annotated_queryset[0].get_config_context())
+
+    def test_multiple_tags_return_distinct_objects(self):
+        """
+        Tagged items use a generic relationship, which results in duplicate rows being returned when queried.
+        This is combatted by by appending distinct() to the config context querysets. This test creates a config
+        context assigned to two tags and ensures objects related by those same two tags result in only a single
+        config context record being returned.
+
+        See https://github.com/netbox-community/netbox/issues/5314
+        """
+        tag_context = ConfigContext.objects.create(
+            name="tag",
+            weight=100,
+            data={
+                "tag": 1
+            }
+        )
+        tag_context.tags.add(self.tag)
+        tag_context.tags.add(self.tag2)
+
+        device = Device.objects.create(
+            name="Device 3",
+            site=self.site,
+            tenant=self.tenant,
+            platform=self.platform,
+            device_role=self.devicerole,
+            device_type=self.devicetype
+        )
+        device.tags.add(self.tag)
+        device.tags.add(self.tag2)
+
+        annotated_queryset = Device.objects.filter(name=device.name).annotate_config_context_data()
+        self.assertEqual(ConfigContext.objects.get_for_object(device).count(), 1)
+        self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())