mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Replace annotate_depth() with annotate_tree()
This commit is contained in:
parent
bdb8263610
commit
0d68d0c059
@ -3,34 +3,20 @@ from utilities.querysets import RestrictedQuerySet
|
|||||||
|
|
||||||
class PrefixQuerySet(RestrictedQuerySet):
|
class PrefixQuerySet(RestrictedQuerySet):
|
||||||
|
|
||||||
def annotate_depth(self, limit=None):
|
def annotate_tree(self):
|
||||||
"""
|
"""
|
||||||
Iterate through a QuerySet of Prefixes and annotate the hierarchical level of each. While it would be preferable
|
Annotate the number of parent and child prefixes for each Prefix. Raw SQL is needed for these subqueries
|
||||||
to do this using .annotate() on the QuerySet to count the unique parents of each prefix, that approach introduces
|
because we need to cast NULL VRF values to integers for comparison. (NULL != NULL).
|
||||||
performance issues at scale.
|
|
||||||
|
|
||||||
Because we're adding a non-field attribute to the model, annotation must be made *after* any QuerySet
|
|
||||||
modifications.
|
|
||||||
"""
|
"""
|
||||||
queryset = self
|
return self.extra(
|
||||||
stack = []
|
select={
|
||||||
for p in queryset:
|
'parents': 'SELECT COUNT(U0."prefix") AS "c" '
|
||||||
try:
|
'FROM "ipam_prefix" U0 '
|
||||||
prev_p = stack[-1]
|
'WHERE (U0."prefix" >> "ipam_prefix"."prefix" '
|
||||||
except IndexError:
|
'AND COALESCE(U0."vrf_id", 0) = COALESCE("ipam_prefix"."vrf_id", 0))',
|
||||||
prev_p = None
|
'children': 'SELECT COUNT(U1."prefix") AS "c" '
|
||||||
if prev_p is not None:
|
'FROM "ipam_prefix" U1 '
|
||||||
while (p.prefix not in prev_p.prefix) or p.prefix == prev_p.prefix:
|
'WHERE (U1."prefix" << "ipam_prefix"."prefix" '
|
||||||
stack.pop()
|
'AND COALESCE(U1."vrf_id", 0) = COALESCE("ipam_prefix"."vrf_id", 0))',
|
||||||
try:
|
}
|
||||||
prev_p = stack[-1]
|
)
|
||||||
except IndexError:
|
|
||||||
prev_p = None
|
|
||||||
break
|
|
||||||
if prev_p is not None:
|
|
||||||
prev_p.has_children = True
|
|
||||||
stack.append(p)
|
|
||||||
p.depth = len(stack) - 1
|
|
||||||
if limit is None:
|
|
||||||
return queryset
|
|
||||||
return list(filter(lambda p: p.depth <= limit, queryset))
|
|
||||||
|
@ -221,9 +221,7 @@ class AggregateView(ObjectView):
|
|||||||
'site', 'role'
|
'site', 'role'
|
||||||
).order_by(
|
).order_by(
|
||||||
'prefix'
|
'prefix'
|
||||||
).annotate_depth(
|
).annotate_tree()
|
||||||
limit=0
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add available prefixes to the table if requested
|
# Add available prefixes to the table if requested
|
||||||
if request.GET.get('show_available', 'true') == 'true':
|
if request.GET.get('show_available', 'true') == 'true':
|
||||||
@ -326,11 +324,6 @@ class PrefixListView(ObjectListView):
|
|||||||
table = tables.PrefixDetailTable
|
table = tables.PrefixDetailTable
|
||||||
template_name = 'ipam/prefix_list.html'
|
template_name = 'ipam/prefix_list.html'
|
||||||
|
|
||||||
def alter_queryset(self, request):
|
|
||||||
# Show only top-level prefixes by default (unless searching)
|
|
||||||
limit = None if request.GET.get('expand') or request.GET.get('q') else 0
|
|
||||||
return self.queryset.annotate_depth(limit=limit)
|
|
||||||
|
|
||||||
|
|
||||||
class PrefixView(ObjectView):
|
class PrefixView(ObjectView):
|
||||||
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
|
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
|
||||||
@ -353,7 +346,7 @@ class PrefixView(ObjectView):
|
|||||||
prefix__net_contains=str(prefix.prefix)
|
prefix__net_contains=str(prefix.prefix)
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
'site', 'role'
|
'site', 'role'
|
||||||
).annotate_depth()
|
).annotate_tree()
|
||||||
parent_prefix_table = tables.PrefixTable(list(parent_prefixes), orderable=False)
|
parent_prefix_table = tables.PrefixTable(list(parent_prefixes), orderable=False)
|
||||||
parent_prefix_table.exclude = ('vrf',)
|
parent_prefix_table.exclude = ('vrf',)
|
||||||
|
|
||||||
@ -386,7 +379,7 @@ class PrefixPrefixesView(ObjectView):
|
|||||||
# Child prefixes table
|
# Child prefixes table
|
||||||
child_prefixes = prefix.get_child_prefixes().restrict(request.user, 'view').prefetch_related(
|
child_prefixes = prefix.get_child_prefixes().restrict(request.user, 'view').prefetch_related(
|
||||||
'site', 'vlan', 'role',
|
'site', 'vlan', 'role',
|
||||||
).annotate_depth(limit=0)
|
).annotate_tree()
|
||||||
|
|
||||||
# Add available prefixes to the table if requested
|
# Add available prefixes to the table if requested
|
||||||
if child_prefixes and request.GET.get('show_available', 'true') == 'true':
|
if child_prefixes and request.GET.get('show_available', 'true') == 'true':
|
||||||
|
Loading…
Reference in New Issue
Block a user