From 5a00939512fb4d61f5754be919652dc742c34e30 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 26 Feb 2020 16:41:59 -0500 Subject: [PATCH] Fixes #4285: Include A/Z termination sites in provider circuits table --- docs/release-notes/version-2.7.md | 1 + netbox/circuits/models.py | 2 ++ netbox/circuits/querysets.py | 15 +++++++++++++++ netbox/circuits/views.py | 13 +++++++------ netbox/netbox/views.py | 14 +++----------- 5 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 netbox/circuits/querysets.py diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index fe8a02190..379151e2a 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -9,6 +9,7 @@ ## Bug Fixes * [#4277](https://github.com/netbox-community/netbox/issues/4277) - Fix filtering of clusters by tenant +* [#4285](https://github.com/netbox-community/netbox/issues/4285) - Include A/Z termination sites in provider circuits table --- diff --git a/netbox/circuits/models.py b/netbox/circuits/models.py index 59f6e2004..812eaa79e 100644 --- a/netbox/circuits/models.py +++ b/netbox/circuits/models.py @@ -10,6 +10,7 @@ from extras.models import CustomFieldModel, ObjectChange, TaggedItem from utilities.models import ChangeLoggedModel from utilities.utils import serialize_object from .choices import * +from .querysets import CircuitQuerySet __all__ = ( @@ -184,6 +185,7 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): object_id_field='obj_id' ) + objects = CircuitQuerySet.as_manager() tags = TaggableManager(through=TaggedItem) csv_headers = [ diff --git a/netbox/circuits/querysets.py b/netbox/circuits/querysets.py new file mode 100644 index 000000000..60956f32a --- /dev/null +++ b/netbox/circuits/querysets.py @@ -0,0 +1,15 @@ +from django.db.models import OuterRef, QuerySet, Subquery + + +class CircuitQuerySet(QuerySet): + + def annotate_sites(self): + """ + Annotate the A and Z termination site names for ordering. + """ + from circuits.models import CircuitTermination + _terminations = CircuitTermination.objects.filter(circuit=OuterRef('pk')) + return self.annotate( + a_side=Subquery(_terminations.filter(term_side='A').values('site__name')[:1]), + z_side=Subquery(_terminations.filter(term_side='Z').values('site__name')[:1]), + ) diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index ba873f23f..b092e1855 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -37,10 +37,14 @@ class ProviderView(PermissionRequiredMixin, View): def get(self, request, slug): provider = get_object_or_404(Provider, slug=slug) - circuits = Circuit.objects.filter(provider=provider).prefetch_related('type', 'tenant', 'terminations__site') + circuits = Circuit.objects.filter( + provider=provider + ).prefetch_related( + 'type', 'tenant', 'terminations__site' + ).annotate_sites() show_graphs = Graph.objects.filter(type__model='provider').exists() - circuits_table = tables.CircuitTable(circuits, orderable=False) + circuits_table = tables.CircuitTable(circuits) circuits_table.columns.hide('provider') paginate = { @@ -142,10 +146,7 @@ class CircuitListView(PermissionRequiredMixin, ObjectListView): _terminations = CircuitTermination.objects.filter(circuit=OuterRef('pk')) queryset = Circuit.objects.prefetch_related( 'provider', 'type', 'tenant', 'terminations__site' - ).annotate( - a_side=Subquery(_terminations.filter(term_side='A').values('site__name')[:1]), - z_side=Subquery(_terminations.filter(term_side='Z').values('site__name')[:1]), - ) + ).annotate_sites() filterset = filters.CircuitFilterSet filterset_form = forms.CircuitFilterForm table = tables.CircuitTable diff --git a/netbox/netbox/views.py b/netbox/netbox/views.py index 904dc7375..05bcea90d 100644 --- a/netbox/netbox/views.py +++ b/netbox/netbox/views.py @@ -1,6 +1,6 @@ from collections import OrderedDict -from django.db.models import Count, F, OuterRef, Subquery +from django.db.models import Count, F from django.shortcuts import render from django.views.generic import View from rest_framework.response import Response @@ -8,7 +8,7 @@ from rest_framework.reverse import reverse from rest_framework.views import APIView from circuits.filters import CircuitFilterSet, ProviderFilterSet -from circuits.models import Circuit, CircuitTermination, Provider +from circuits.models import Circuit, Provider from circuits.tables import CircuitTable, ProviderTable from dcim.filters import ( CableFilterSet, DeviceFilterSet, DeviceTypeFilterSet, PowerFeedFilterSet, RackFilterSet, RackGroupFilterSet, SiteFilterSet, @@ -50,15 +50,7 @@ SEARCH_TYPES = OrderedDict(( 'permission': 'circuits.view_circuit', 'queryset': Circuit.objects.prefetch_related( 'type', 'provider', 'tenant', 'terminations__site' - ).annotate( - # Annotate A/Z terminations - a_side=Subquery( - CircuitTermination.objects.filter(circuit=OuterRef('pk')).filter(term_side='A').values('site__name')[:1] - ), - z_side=Subquery( - CircuitTermination.objects.filter(circuit=OuterRef('pk')).filter(term_side='Z').values('site__name')[:1] - ), - ), + ).annotate_sites(), 'filterset': CircuitFilterSet, 'table': CircuitTable, 'url': 'circuits:circuit_list',