فهرست منبع

Merge pull request #3550 from netbox-community/3259-cable-filters

3259 cable filters
Jeremy Stretch 6 سال پیش
والد
کامیت
63ad93afd0
4فایلهای تغییر یافته به همراه121 افزوده شده و 30 حذف شده
  1. 26 14
      CHANGELOG.md
  2. 27 16
      netbox/dcim/filters.py
  3. 46 0
      netbox/dcim/migrations/0075_cable_devices.py
  4. 22 0
      netbox/dcim/models.py

+ 26 - 14
CHANGELOG.md

@@ -1,24 +1,34 @@
+v2.6.6 (FUTURE)
+
+## Enhancements
+
+* [#3259](https://github.com/netbox-community/netbox/issues/3259) - Add `rack` and `site` filters for cables
+
+---
+
 v2.6.5 (2019-09-25)
 
 ## Enhancements
 
-* [#3297](https://github.com/netbox-community/netbox/issues/3297) -  Include reserved units when calculating rack utilization
-* [#3347](https://github.com/netbox-community/netbox/issues/3347) -  Extend upgrade script to automatically remove stale content types
-* [#3352](https://github.com/netbox-community/netbox/issues/3352) -  Enable filtering changelog API by `changed_object_id`
-* [#3515](https://github.com/netbox-community/netbox/issues/3515) -  Enable export templates for inventory items
-* [#3524](https://github.com/netbox-community/netbox/issues/3524) -  Enable bulk editing of power outlet/power port associations
-* [#3529](https://github.com/netbox-community/netbox/issues/3529) -  Enable filtering circuits list by region
+* [#3297](https://github.com/netbox-community/netbox/issues/3297) - Include reserved units when calculating rack utilization
+* [#3347](https://github.com/netbox-community/netbox/issues/3347) - Extend upgrade script to automatically remove stale content types
+* [#3352](https://github.com/netbox-community/netbox/issues/3352) - Enable filtering changelog API by `changed_object_id`
+* [#3515](https://github.com/netbox-community/netbox/issues/3515) - Enable export templates for inventory items
+* [#3524](https://github.com/netbox-community/netbox/issues/3524) - Enable bulk editing of power outlet/power port associations
+* [#3529](https://github.com/netbox-community/netbox/issues/3529) - Enable filtering circuits list by region
 
 ## Bug Fixes
 
-* [#3435](https://github.com/netbox-community/netbox/issues/3435) -  Change IP/prefix CSV export to reference VRF name instead of RD
-* [#3464](https://github.com/netbox-community/netbox/issues/3464) -  Fix foreground text color on color picker fields
-* [#3519](https://github.com/netbox-community/netbox/issues/3519) -  Prevent cables from being terminated to virtual/wireless interfaces via API
-* [#3521](https://github.com/netbox-community/netbox/issues/3521) -  Fix error in `parseURL` related to variables in API URL
-* [#3531](https://github.com/netbox-community/netbox/issues/3531) -  Fixed rack role foreground color
-* [#3534](https://github.com/netbox-community/netbox/issues/3534) -  Added blank option for untagged VLANs
-* [#3540](https://github.com/netbox-community/netbox/issues/3540) -  Fixed virtual machine interface edit with new inline vlan edit fields
-* [#3543](https://github.com/netbox-community/netbox/issues/3543) -  Added inline VLAN editing to virtual machine interfaces
+* [#3435](https://github.com/netbox-community/netbox/issues/3435) - Change IP/prefix CSV export to reference VRF name instead of RD
+* [#3464](https://github.com/netbox-community/netbox/issues/3464) - Fix foreground text color on color picker fields
+* [#3519](https://github.com/netbox-community/netbox/issues/3519) - Prevent cables from being terminated to virtual/wireless interfaces via API
+* [#3521](https://github.com/netbox-community/netbox/issues/3521) - Fix error in `parseURL` related to variables in API URL
+* [#3531](https://github.com/netbox-community/netbox/issues/3531) - Fixed rack role foreground color
+* [#3534](https://github.com/netbox-community/netbox/issues/3534) - Added blank option for untagged VLANs
+* [#3540](https://github.com/netbox-community/netbox/issues/3540) - Fixed virtual machine interface edit with new inline vlan edit fields
+* [#3543](https://github.com/netbox-community/netbox/issues/3543) - Added inline VLAN editing to virtual machine interfaces
+
+---
 
 v2.6.4 (2019-09-19)
 
@@ -39,6 +49,8 @@ v2.6.4 (2019-09-19)
 * [#3513](https://github.com/netbox-community/netbox/issues/3513) - Fix assignment of tags when creating front/rear ports
 * [#3514](https://github.com/netbox-community/netbox/issues/3514) - Label TextVar fields when rendering custom script forms
 
+---
+
 v2.6.3 (2019-09-04)
 
 ## New Features

+ 27 - 16
netbox/dcim/filters.py

@@ -1,6 +1,5 @@
 import django_filters
 from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
 from django.db.models import Q
 
 from extras.filters import CustomFieldFilterSet, LocalConfigContextFilter
@@ -931,13 +930,28 @@ class CableFilter(django_filters.FilterSet):
     color = django_filters.MultipleChoiceFilter(
         choices=COLOR_CHOICES
     )
-    device = django_filters.CharFilter(
-        method='filter_connected_device',
-        field_name='name'
+    device_id = MultiValueNumberFilter(
+        method='filter_device'
+    )
+    device = MultiValueNumberFilter(
+        method='filter_device',
+        field_name='device__name'
+    )
+    rack_id = MultiValueNumberFilter(
+        method='filter_device',
+        field_name='device__rack_id'
+    )
+    rack = MultiValueNumberFilter(
+        method='filter_device',
+        field_name='device__rack__name'
+    )
+    site_id = MultiValueNumberFilter(
+        method='filter_device',
+        field_name='device__site_id'
     )
-    device_id = django_filters.CharFilter(
-        method='filter_connected_device',
-        field_name='pk'
+    site = MultiValueNumberFilter(
+        method='filter_device',
+        field_name='device__site__slug'
     )
 
     class Meta:
@@ -949,15 +963,12 @@ class CableFilter(django_filters.FilterSet):
             return queryset
         return queryset.filter(label__icontains=value)
 
-    def filter_connected_device(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        try:
-            device = Device.objects.get(**{name: value})
-        except ObjectDoesNotExist:
-            return queryset.none()
-        cable_pks = device.get_cables(pk_list=True)
-        return queryset.filter(pk__in=cable_pks)
+    def filter_device(self, queryset, name, value):
+        queryset = queryset.filter(
+            Q(**{'_termination_a_{}__in'.format(name): value}) |
+            Q(**{'_termination_b_{}__in'.format(name): value})
+        )
+        return queryset
 
 
 class ConsoleConnectionFilter(django_filters.FilterSet):

+ 46 - 0
netbox/dcim/migrations/0075_cable_devices.py

@@ -0,0 +1,46 @@
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+def cache_cable_devices(apps, schema_editor):
+    Cable = apps.get_model('dcim', 'Cable')
+
+    # Cache A/B termination devices on all existing Cables. Note that the custom save() method on Cable is not
+    # available during a migration, so we replicate its logic here.
+    for cable in Cable.objects.all():
+
+        termination_a_model = apps.get_model(cable.termination_a_type.app_label, cable.termination_a_type.model)
+        if hasattr(termination_a_model, 'device'):
+            termination_a = termination_a_model.objects.get(pk=cable.termination_a_id)
+            cable._termination_a_device = termination_a.device
+
+        termination_b_model = apps.get_model(cable.termination_b_type.app_label, cable.termination_b_type.model)
+        if hasattr(termination_b_model, 'device'):
+            termination_b = termination_b_model.objects.get(pk=cable.termination_b_id)
+            cable._termination_b_device = termination_b.device
+
+        cable.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('dcim', '0074_increase_field_length_platform_name_slug'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='cable',
+            name='_termination_a_device',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.Device'),
+        ),
+        migrations.AddField(
+            model_name='cable',
+            name='_termination_b_device',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.Device'),
+        ),
+        migrations.RunPython(
+            code=cache_cable_devices,
+            reverse_code=migrations.RunPython.noop
+        ),
+    ]

+ 22 - 0
netbox/dcim/models.py

@@ -2781,6 +2781,22 @@ class Cable(ChangeLoggedModel):
         blank=True,
         null=True
     )
+    # Cache the associated device (where applicable) for the A and B terminations. This enables filtering of Cables by
+    # their associated Devices.
+    _termination_a_device = models.ForeignKey(
+        to=Device,
+        on_delete=models.CASCADE,
+        related_name='+',
+        blank=True,
+        null=True
+    )
+    _termination_b_device = models.ForeignKey(
+        to=Device,
+        on_delete=models.CASCADE,
+        related_name='+',
+        blank=True,
+        null=True
+    )
 
     csv_headers = [
         'termination_a_type', 'termination_a_id', 'termination_b_type', 'termination_b_id', 'type', 'status', 'label',
@@ -2895,6 +2911,12 @@ class Cable(ChangeLoggedModel):
         if self.length and self.length_unit:
             self._abs_length = to_meters(self.length, self.length_unit)
 
+        # Store the parent Device for the A and B terminations (if applicable) to enable filtering
+        if hasattr(self.termination_a, 'device'):
+            self._termination_a_device = self.termination_a.device
+        if hasattr(self.termination_b, 'device'):
+            self._termination_b_device = self.termination_b.device
+
         super().save(*args, **kwargs)
 
     def to_csv(self):