mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
initial work on config context performance improvements
This commit is contained in:
@ -340,7 +340,18 @@ class DeviceViewSet(CustomFieldModelViewSet):
|
|||||||
queryset = Device.objects.prefetch_related(
|
queryset = Device.objects.prefetch_related(
|
||||||
'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'site', 'rack', 'parent_bay',
|
'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'site', 'rack', 'parent_bay',
|
||||||
'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'tags',
|
'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'tags',
|
||||||
)
|
).add_config_context_annotation()
|
||||||
|
|
||||||
|
#queryset = Device.objects.annotate(
|
||||||
|
# config_contexts=Subquery(
|
||||||
|
# ConfigContext.objects.filter(
|
||||||
|
# Q(sites=OuterRef('site')) | Q(sites=None)
|
||||||
|
# ).annotate(
|
||||||
|
# _data=EmptyGroupByJSONBAgg('data')
|
||||||
|
# ).values("_data")
|
||||||
|
# )
|
||||||
|
#)
|
||||||
|
|
||||||
filterset_class = filters.DeviceFilterSet
|
filterset_class = filters.DeviceFilterSet
|
||||||
|
|
||||||
def get_serializer_class(self):
|
def get_serializer_class(self):
|
||||||
|
@ -15,6 +15,7 @@ from taggit.managers import TaggableManager
|
|||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from extras.models import ChangeLoggedModel, ConfigContextModel, CustomFieldModel, TaggedItem
|
from extras.models import ChangeLoggedModel, ConfigContextModel, CustomFieldModel, TaggedItem
|
||||||
|
from extras.querysets import ConfigContextQuerySetMixin
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from utilities.choices import ColorChoices
|
from utilities.choices import ColorChoices
|
||||||
from utilities.fields import ColorField, NaturalOrderingField
|
from utilities.fields import ColorField, NaturalOrderingField
|
||||||
@ -594,7 +595,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
|
|||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
tags = TaggableManager(through=TaggedItem)
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = ConfigContextQuerySetMixin.as_manager()
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
'name', 'device_role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status',
|
'name', 'device_role', 'tenant', 'manufacturer', 'device_type', 'platform', 'serial', 'asset_tag', 'status',
|
||||||
|
@ -542,8 +542,11 @@ class ConfigContextModel(models.Model):
|
|||||||
|
|
||||||
# Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs
|
# Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs
|
||||||
data = OrderedDict()
|
data = OrderedDict()
|
||||||
for context in ConfigContext.objects.get_for_object(self):
|
#for context in ConfigContext.objects.get_for_object(self):
|
||||||
data = deepmerge(data, context.data)
|
# data = deepmerge(data, context.data)
|
||||||
|
|
||||||
|
for context in self.config_contexts:
|
||||||
|
data = deepmerge(data, context)
|
||||||
|
|
||||||
# If the object has local config context data defined, merge it last
|
# If the object has local config context data defined, merge it last
|
||||||
if self.local_context_data:
|
if self.local_context_data:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.db.models import Q, QuerySet
|
from django.contrib.postgres.aggregates import JSONBAgg
|
||||||
|
from django.db.models import OuterRef, Subquery, Q, QuerySet
|
||||||
|
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
|
|
||||||
@ -57,3 +58,51 @@ class ConfigContextQuerySet(RestrictedQuerySet):
|
|||||||
Q(tags__slug__in=obj.tags.slugs()) | Q(tags=None),
|
Q(tags__slug__in=obj.tags.slugs()) | Q(tags=None),
|
||||||
is_active=True,
|
is_active=True,
|
||||||
).order_by('weight', 'name')
|
).order_by('weight', 'name')
|
||||||
|
|
||||||
|
|
||||||
|
class EmptyGroupByJSONBAgg(JSONBAgg):
|
||||||
|
contains_aggregate = False
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigContextQuerySetMixin(RestrictedQuerySet):
|
||||||
|
|
||||||
|
def add_config_context_annotation(self):
|
||||||
|
from extras.models import ConfigContext
|
||||||
|
return self.annotate(
|
||||||
|
config_contexts=Subquery(
|
||||||
|
ConfigContext.objects.filter(
|
||||||
|
self._add_config_context_filters()
|
||||||
|
).order_by(
|
||||||
|
'weight',
|
||||||
|
'name'
|
||||||
|
).annotate(
|
||||||
|
_data=EmptyGroupByJSONBAgg('data')
|
||||||
|
).values("_data")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _add_config_context_filters(self):
|
||||||
|
|
||||||
|
|
||||||
|
if self.model._meta.model_name == 'device':
|
||||||
|
return Q(
|
||||||
|
Q(sites=OuterRef('site')) | Q(sites=None),
|
||||||
|
Q(roles=OuterRef('device_role')) | Q(roles=None),
|
||||||
|
Q(platforms=OuterRef('platform')) | Q(platforms=None),
|
||||||
|
Q(tenant_groups=OuterRef('tenant__group')) | Q(tenant_groups=None),
|
||||||
|
Q(tenants=OuterRef('tenant')) | Q(tenants=None),
|
||||||
|
Q(tags=OuterRef('tags')) | Q(tags=None),
|
||||||
|
is_active=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return Q(
|
||||||
|
Q(sites=OuterRef('site')) | Q(sites=None),
|
||||||
|
Q(roles=OuterRef('role')) | Q(roles=None),
|
||||||
|
Q(platforms=OuterRef('platform')) | Q(platforms=None),
|
||||||
|
Q(cluster_groups=OuterRef('cluster__group')) | Q(cluster_groups=None),
|
||||||
|
Q(clusters=OuterRef('cluster')) | Q(clusters=None),
|
||||||
|
Q(tenant_groups=OuterRef('tenant__group')) | Q(tenant_groups=None),
|
||||||
|
Q(tenants=OuterRef('tenant')) | Q(tenants=None),
|
||||||
|
Q(tags=OuterRef('tags')) | Q(tags=None),
|
||||||
|
is_active=True,
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user