mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
fixes #5387 - Fix error when rendering config contexts when objects have multiple tags assigned (#5447)
This commit is contained in:
parent
13a13f3943
commit
53f330dbe8
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
* [#5383](https://github.com/netbox-community/netbox/issues/5383) - Fix setting user password via REST API
|
* [#5383](https://github.com/netbox-community/netbox/issues/5383) - Fix setting user password via REST API
|
||||||
* [#5396](https://github.com/netbox-community/netbox/issues/5396) - Fix uniqueness constraint for virtual machine names
|
* [#5396](https://github.com/netbox-community/netbox/issues/5396) - Fix uniqueness constraint for virtual machine names
|
||||||
|
* [#5387](https://github.com/netbox-community/netbox/issues/5387) - Fix error when rendering config contexts when objects have multiple tags assigned
|
||||||
* [#5407](https://github.com/netbox-community/netbox/issues/5407) - Add direct link to secret on secrets list
|
* [#5407](https://github.com/netbox-community/netbox/issues/5407) - Add direct link to secret on secrets list
|
||||||
* [#5408](https://github.com/netbox-community/netbox/issues/5408) - Fix updating secrets without setting new plaintext
|
* [#5408](https://github.com/netbox-community/netbox/issues/5408) - Fix updating secrets without setting new plaintext
|
||||||
* [#5410](https://github.com/netbox-community/netbox/issues/5410) - Restore tags field on cable connection forms
|
* [#5410](https://github.com/netbox-community/netbox/issues/5410) - Restore tags field on cable connection forms
|
||||||
|
@ -2,6 +2,7 @@ from collections import OrderedDict
|
|||||||
|
|
||||||
from django.db.models import OuterRef, Subquery, Q
|
from django.db.models import OuterRef, Subquery, Q
|
||||||
|
|
||||||
|
from extras.models.tags import TaggedItem
|
||||||
from utilities.query_functions import EmptyGroupByJSONBAgg, OrderableJSONBAgg
|
from utilities.query_functions import EmptyGroupByJSONBAgg, OrderableJSONBAgg
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
|
|
||||||
@ -99,11 +100,25 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
|||||||
|
|
||||||
def _get_config_context_filters(self):
|
def _get_config_context_filters(self):
|
||||||
# Construct the set of Q objects for the specific object types
|
# Construct the set of Q objects for the specific object types
|
||||||
|
tag_query_filters = {
|
||||||
|
"object_id": OuterRef(OuterRef('pk')),
|
||||||
|
"content_type__app_label": self.model._meta.app_label,
|
||||||
|
"content_type__model": self.model._meta.model_name
|
||||||
|
}
|
||||||
base_query = Q(
|
base_query = Q(
|
||||||
Q(platforms=OuterRef('platform')) | Q(platforms=None),
|
Q(platforms=OuterRef('platform')) | Q(platforms=None),
|
||||||
Q(tenant_groups=OuterRef('tenant__group')) | Q(tenant_groups=None),
|
Q(tenant_groups=OuterRef('tenant__group')) | Q(tenant_groups=None),
|
||||||
Q(tenants=OuterRef('tenant')) | Q(tenants=None),
|
Q(tenants=OuterRef('tenant')) | Q(tenants=None),
|
||||||
Q(tags=OuterRef('tags')) | Q(tags=None),
|
Q(
|
||||||
|
tags__pk__in=Subquery(
|
||||||
|
TaggedItem.objects.filter(
|
||||||
|
**tag_query_filters
|
||||||
|
).values_list(
|
||||||
|
'tag_id',
|
||||||
|
flat=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) | Q(tags=None),
|
||||||
is_active=True,
|
is_active=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -363,3 +363,46 @@ class ConfigContextTest(TestCase):
|
|||||||
annotated_queryset = Device.objects.filter(name=device.name).annotate_config_context_data()
|
annotated_queryset = Device.objects.filter(name=device.name).annotate_config_context_data()
|
||||||
self.assertEqual(ConfigContext.objects.get_for_object(device).count(), 1)
|
self.assertEqual(ConfigContext.objects.get_for_object(device).count(), 1)
|
||||||
self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())
|
self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())
|
||||||
|
|
||||||
|
def test_multiple_tags_return_distinct_objects_with_seperate_config_contexts(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.
|
||||||
|
|
||||||
|
This test case is seperate from the above in that it deals with multiple config context objects in play.
|
||||||
|
|
||||||
|
See https://github.com/netbox-community/netbox/issues/5387
|
||||||
|
"""
|
||||||
|
tag_context_1 = ConfigContext.objects.create(
|
||||||
|
name="tag-1",
|
||||||
|
weight=100,
|
||||||
|
data={
|
||||||
|
"tag": 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tag_context_1.tags.add(self.tag)
|
||||||
|
tag_context_2 = ConfigContext.objects.create(
|
||||||
|
name="tag-2",
|
||||||
|
weight=100,
|
||||||
|
data={
|
||||||
|
"tag": 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tag_context_2.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(), 2)
|
||||||
|
self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())
|
||||||
|
Loading…
Reference in New Issue
Block a user