Browse Source

Fixes #1079: Order interfaces naturally via API

Jeremy Stretch 7 years ago
parent
commit
cd263484c3
2 changed files with 26 additions and 9 deletions
  1. 21 3
      netbox/dcim/filters.py
  2. 5 6
      netbox/dcim/models.py

+ 21 - 3
netbox/dcim/filters.py

@@ -433,12 +433,12 @@ class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
 
 
 class DeviceComponentFilterSet(django_filters.FilterSet):
-    device_id = django_filters.ModelMultipleChoiceFilter(
+    device_id = django_filters.ModelChoiceFilter(
         name='device',
         queryset=Device.objects.all(),
         label='Device (ID)',
     )
-    device = django_filters.ModelMultipleChoiceFilter(
+    device = django_filters.ModelChoiceFilter(
         name='device__name',
         queryset=Device.objects.all(),
         to_field_name='name',
@@ -474,7 +474,17 @@ class PowerOutletFilter(DeviceComponentFilterSet):
         fields = ['name']
 
 
-class InterfaceFilter(DeviceComponentFilterSet):
+class InterfaceFilter(django_filters.FilterSet):
+    device = django_filters.CharFilter(
+        method='filter_device',
+        name='name',
+        label='Device',
+    )
+    device_id = django_filters.NumberFilter(
+        method='filter_device',
+        name='pk',
+        label='Device (ID)',
+    )
     type = django_filters.CharFilter(
         method='filter_type',
         label='Interface type',
@@ -493,6 +503,14 @@ class InterfaceFilter(DeviceComponentFilterSet):
         model = Interface
         fields = ['name', 'form_factor']
 
+    def filter_device(self, queryset, name, value):
+        try:
+            device = Device.objects.select_related('device_type').get(**{name: value})
+            ordering = device.device_type.interface_ordering
+            return queryset.filter(device=device).order_naturally(ordering)
+        except Device.DoesNotExist:
+            return queryset.none()
+
     def filter_type(self, queryset, name, value):
         value = value.strip().lower()
         if value == 'physical':

+ 5 - 6
netbox/dcim/models.py

@@ -816,7 +816,7 @@ class PowerOutletTemplate(models.Model):
         return self.name
 
 
-class InterfaceManager(models.Manager):
+class InterfaceQuerySet(models.QuerySet):
 
     def order_naturally(self, method=IFACE_ORDERING_POSITION):
         """
@@ -841,13 +841,12 @@ class InterfaceManager(models.Manager):
         The original `name` field is taken as a whole to serve as a fallback in the event interfaces do not match any of
         the prescribed fields.
         """
-        queryset = self.get_queryset()
-        sql_col = '{}.name'.format(queryset.model._meta.db_table)
+        sql_col = '{}.name'.format(self.model._meta.db_table)
         ordering = {
             IFACE_ORDERING_POSITION: ('_slot', '_subslot', '_position', '_channel', '_vc', '_type', 'name'),
             IFACE_ORDERING_NAME: ('_type', '_slot', '_subslot', '_position', '_channel', '_vc', 'name'),
         }[method]
-        return queryset.extra(select={
+        return self.extra(select={
             '_type': "SUBSTRING({} FROM '^([^0-9]+)')".format(sql_col),
             '_slot': "CAST(SUBSTRING({} FROM '([0-9]+)\/[0-9]+\/[0-9]+(:[0-9]+)?(\.[0-9]+)?$') AS integer)".format(sql_col),
             '_subslot': "CAST(SUBSTRING({} FROM '([0-9]+)\/[0-9]+(:[0-9]+)?(\.[0-9]+)?$') AS integer)".format(sql_col),
@@ -867,7 +866,7 @@ class InterfaceTemplate(models.Model):
     form_factor = models.PositiveSmallIntegerField(choices=IFACE_FF_CHOICES, default=IFACE_FF_10GE_SFP_PLUS)
     mgmt_only = models.BooleanField(default=False, verbose_name='Management only')
 
-    objects = InterfaceManager()
+    objects = InterfaceQuerySet.as_manager()
 
     class Meta:
         ordering = ['device_type', 'name']
@@ -1317,7 +1316,7 @@ class Interface(models.Model):
                                     help_text="This interface is used only for out-of-band management")
     description = models.CharField(max_length=100, blank=True)
 
-    objects = InterfaceManager()
+    objects = InterfaceQuerySet.as_manager()
 
     class Meta:
         ordering = ['device', 'name']