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

Fixes #13047: Add annotate_asn_count() to ASNRange manager

Jeremy Stretch 2 лет назад
Родитель
Сommit
5f0922713f
4 измененных файлов с 35 добавлено и 13 удалено
  1. 3 0
      netbox/ipam/models/asns.py
  2. 25 1
      netbox/ipam/querysets.py
  3. 4 5
      netbox/ipam/tables/asn.py
  4. 3 7
      netbox/ipam/views.py

+ 3 - 0
netbox/ipam/models/asns.py

@@ -4,6 +4,7 @@ from django.urls import reverse
 from django.utils.translation import gettext as _
 
 from ipam.fields import ASNField
+from ipam.querysets import ASNRangeQuerySet
 from netbox.models import OrganizationalModel, PrimaryModel
 
 __all__ = (
@@ -37,6 +38,8 @@ class ASNRange(OrganizationalModel):
         null=True
     )
 
+    objects = ASNRangeQuerySet.as_manager()
+
     class Meta:
         ordering = ('name',)
         verbose_name = 'ASN range'

+ 25 - 1
netbox/ipam/querysets.py

@@ -1,9 +1,33 @@
 from django.contrib.contenttypes.models import ContentType
-from django.db.models import Q
+from django.db.models import Count, OuterRef, Q, Subquery, Value
 from django.db.models.expressions import RawSQL
 
 from utilities.querysets import RestrictedQuerySet
 
+__all__ = (
+    'ASNRangeQuerySet',
+    'PrefixQuerySet',
+    'VLANQuerySet',
+)
+
+
+class ASNRangeQuerySet(RestrictedQuerySet):
+
+    def annotate_asn_counts(self):
+        """
+        Annotate the number of ASNs which appear within each range.
+        """
+        from .models import ASN
+
+        # Because ASN does not have a foreign key to ASNRange, we create a fake column "_" with a consistent value
+        # that we can use to count ASNs and return a single value per ASNRange.
+        asns = ASN.objects.filter(
+            asn__gte=OuterRef('start'),
+            asn__lte=OuterRef('end')
+        ).order_by().annotate(_=Value(1)).values('_').annotate(c=Count('*')).values('c')
+
+        return self.annotate(asn_count=Subquery(asns))
+
 
 class PrefixQuerySet(RestrictedQuerySet):
 

+ 4 - 5
netbox/ipam/tables/asn.py

@@ -21,10 +21,8 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable):
     tags = columns.TagColumn(
         url_name='ipam:asnrange_list'
     )
-    asn_count = columns.LinkedCountColumn(
-        viewname='ipam:asn_list',
-        url_params={'asn_id': 'pk'},
-        verbose_name=_('ASN Count')
+    asn_count = tables.Column(
+        verbose_name=_('ASNs')
     )
 
     class Meta(NetBoxTable.Meta):
@@ -59,7 +57,8 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable):
         verbose_name=_('Provider Count')
     )
     sites = columns.ManyToManyColumn(
-        linkify_item=True
+        linkify_item=True,
+        verbose_name=_('Sites')
     )
     comments = columns.MarkdownColumn()
     tags = columns.TagColumn(

+ 3 - 7
netbox/ipam/views.py

@@ -198,7 +198,7 @@ class RIRBulkDeleteView(generic.BulkDeleteView):
 #
 
 class ASNRangeListView(generic.ObjectListView):
-    queryset = ASNRange.objects.all()
+    queryset = ASNRange.objects.annotate_asn_counts()
     filterset = filtersets.ASNRangeFilterSet
     filterset_form = forms.ASNRangeFilterForm
     table = tables.ASNRangeTable
@@ -247,18 +247,14 @@ class ASNRangeBulkImportView(generic.BulkImportView):
 
 
 class ASNRangeBulkEditView(generic.BulkEditView):
-    queryset = ASNRange.objects.annotate(
-        site_count=count_related(Site, 'asns')
-    )
+    queryset = ASNRange.objects.annotate_asn_counts()
     filterset = filtersets.ASNRangeFilterSet
     table = tables.ASNRangeTable
     form = forms.ASNRangeBulkEditForm
 
 
 class ASNRangeBulkDeleteView(generic.BulkDeleteView):
-    queryset = ASNRange.objects.annotate(
-        site_count=count_related(Site, 'asns')
-    )
+    queryset = ASNRange.objects.annotate_asn_counts()
     filterset = filtersets.ASNRangeFilterSet
     table = tables.ASNRangeTable