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

Merge pull request #3553 from chambersh1129/develop

Replace all instances of .extra() in QuerySets with annotations #3117
kobayashi 6 лет назад
Родитель
Сommit
e223c88548
3 измененных файлов с 12 добавлено и 10 удалено
  1. 1 1
      netbox/ipam/querysets.py
  2. 5 4
      netbox/ipam/views.py
  3. 6 5
      netbox/utilities/managers.py

+ 1 - 1
netbox/ipam/querysets.py

@@ -6,7 +6,7 @@ class PrefixQuerySet(QuerySet):
     def annotate_depth(self, limit=None):
         """
         Iterate through a QuerySet of Prefixes and annotate the hierarchical level of each. While it would be preferable
-        to do this using .extra() on the QuerySet to count the unique parents of each prefix, that approach introduces
+        to do this using .annotate() on the QuerySet to count the unique parents of each prefix, that approach introduces
         performance issues at scale.
 
         Because we're adding a non-field attribute to the model, annotation must be made *after* any QuerySet

+ 5 - 4
netbox/ipam/views.py

@@ -2,6 +2,7 @@ import netaddr
 from django.conf import settings
 from django.contrib.auth.mixins import PermissionRequiredMixin
 from django.db.models import Count, Q
+from django.db.models.expressions import RawSQL
 from django.shortcuts import get_object_or_404, redirect, render
 from django.views.generic import View
 from django_tables2 import RequestConfig
@@ -291,10 +292,10 @@ class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 class AggregateListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'ipam.view_aggregate'
-    # TODO: Replace raw SQL
-    queryset = Aggregate.objects.prefetch_related('rir').extra(select={
-        'child_count': 'SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix',
-    })
+    queryset = Aggregate.objects.prefetch_related('rir').annotate(
+        child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ())
+    )
+
     filter = filters.AggregateFilter
     filter_form = forms.AggregateFilterForm
     table = tables.AggregateDetailTable

+ 6 - 5
netbox/utilities/managers.py

@@ -1,4 +1,5 @@
 from django.db.models import Manager
+from django.db.models.expressions import RawSQL
 
 NAT1 = r"CAST(SUBSTRING({}.{} FROM '^(\d{{1,9}})') AS integer)"
 NAT2 = r"SUBSTRING({}.{} FROM '^\d*(.*?)\d*$')"
@@ -21,11 +22,11 @@ class NaturalOrderingManager(Manager):
         db_field = self.natural_order_field
 
         # Append the three subfields derived from the designated natural ordering field
-        queryset = queryset.extra(select={
-            '_nat1': NAT1.format(db_table, db_field),
-            '_nat2': NAT2.format(db_table, db_field),
-            '_nat3': NAT3.format(db_table, db_field),
-        })
+        queryset = (
+            queryset.annotate(_nat1=RawSQL(NAT1.format(db_table, db_field), ()))
+            .annotate(_nat2=RawSQL(NAT2.format(db_table, db_field), ()))
+            .annotate(_nat3=RawSQL(NAT3.format(db_table, db_field), ()))
+        )
 
         # Replace any instance of the designated natural ordering field with its three subfields
         ordering = []