diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 4f5edbee8..1c4ec7838 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -542,7 +542,7 @@ class VirtualChassisViewSet(ModelViewSet): class PowerPanelViewSet(ModelViewSet): queryset = PowerPanel.objects.all() serializer_class = serializers.PowerPanelSerializer - # filterset_class = filters.PowerPanelFilter + filterset_class = filters.PowerPanelFilter # @@ -552,7 +552,7 @@ class PowerPanelViewSet(ModelViewSet): class PowerFeedViewSet(ModelViewSet): queryset = PowerFeed.objects.all() serializer_class = serializers.PowerFeedSerializer - # filterset_class = filters.PowerFeedFilter + filterset_class = filters.PowerFeedFilter # diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 2e303e325..c4db4ef83 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -15,8 +15,9 @@ from .constants import * from .models import ( Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, - InventoryItem, Manufacturer, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, - RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, + InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, + PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, + VirtualChassis, ) @@ -37,7 +38,7 @@ class RegionFilter(NameSlugSearchFilterSet): fields = ['name', 'slug'] -class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet): +class SiteFilter(CustomFieldFilterSet): id__in = NumericInFilter( field_name='id', lookup_expr='in' @@ -122,7 +123,7 @@ class RackRoleFilter(NameSlugSearchFilterSet): fields = ['name', 'slug', 'color'] -class RackFilter(CustomFieldFilterSet, django_filters.FilterSet): +class RackFilter(CustomFieldFilterSet): id__in = NumericInFilter( field_name='id', lookup_expr='in' @@ -1065,3 +1066,81 @@ class InterfaceConnectionFilter(django_filters.FilterSet): Q(device__name__icontains=value) | Q(_connected_interface__device__name__icontains=value) ) + + +class PowerPanelFilter(django_filters.FilterSet): + id__in = NumericInFilter( + field_name='id', + lookup_expr='in' + ) + q = django_filters.CharFilter( + method='search', + label='Search', + ) + site_id = django_filters.ModelMultipleChoiceFilter( + queryset=Site.objects.all(), + label='Site (ID)', + ) + site = django_filters.ModelMultipleChoiceFilter( + field_name='site__slug', + queryset=Site.objects.all(), + to_field_name='slug', + label='Site name (slug)', + ) + rack_group_id = django_filters.ModelMultipleChoiceFilter( + field_name='rack_group', + queryset=RackGroup.objects.all(), + label='Rack group (ID)', + ) + + class Meta: + model = PowerPanel + fields = ['name'] + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + qs_filter = ( + Q(name__icontains=value) + ) + return queryset.filter(qs_filter) + + +class PowerFeedFilter(CustomFieldFilterSet): + id__in = NumericInFilter( + field_name='id', + lookup_expr='in' + ) + q = django_filters.CharFilter( + method='search', + label='Search', + ) + site_id = django_filters.ModelMultipleChoiceFilter( + field_name='power_panel__site', + queryset=Site.objects.all(), + label='Site (ID)', + ) + site = django_filters.ModelMultipleChoiceFilter( + field_name='power_panel__site__slug', + queryset=Site.objects.all(), + to_field_name='slug', + label='Site name (slug)', + ) + rack_id = django_filters.ModelMultipleChoiceFilter( + field_name='rack', + queryset=Rack.objects.all(), + label='Rack (ID)', + ) + + class Meta: + model = PowerFeed + fields = ['name', 'status', 'type', 'supply', 'phase'] + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + qs_filter = ( + Q(name__icontains=value) | + Q(comments__icontains=value) + ) + return queryset.filter(qs_filter) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 7f0a3265c..fd37f2839 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -3208,6 +3208,34 @@ class PowerPanelCSVForm(forms.ModelForm): fields = PowerPanel.csv_headers +class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm): + model = PowerPanel + q = forms.CharField( + required=False, + label='Search' + ) + site = FilterChoiceField( + queryset=Site.objects.all(), + to_field_name='slug', + widget=APISelectMultiple( + api_url="/api/dcim/sites/", + value_field="slug", + filter_for={ + 'rack_id': 'site', + } + ) + ) + rack_group_id = FilterChoiceField( + queryset=RackGroup.objects.all(), + label='Rack group (ID)', + null_label='-- None --', + widget=APISelectMultiple( + api_url="/api/dcim/rack-groups/", + null_option=True, + ) + ) + + # # Power feeds # @@ -3333,3 +3361,51 @@ class PowerFeedBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd nullable_fields = [ 'rackgroup', 'comments', ] + + +class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm): + model = PowerFeed + q = forms.CharField( + required=False, + label='Search' + ) + site = FilterChoiceField( + queryset=Site.objects.all(), + to_field_name='slug', + widget=APISelectMultiple( + api_url="/api/dcim/sites/", + value_field="slug", + filter_for={ + 'rack_id': 'site', + } + ) + ) + rack_id = FilterChoiceField( + queryset=Rack.objects.all(), + label='Rack', + null_label='-- None --', + widget=APISelectMultiple( + api_url="/api/dcim/racks/", + null_option=True, + ) + ) + status = forms.MultipleChoiceField( + choices=POWERFEED_STATUS_CHOICES, + required=False, + widget=StaticSelect2Multiple() + ) + type = forms.ChoiceField( + choices=add_blank_choice(POWERFEED_TYPE_CHOICES), + required=False, + widget=StaticSelect2() + ) + supply = forms.ChoiceField( + choices=add_blank_choice(POWERFEED_SUPPLY_CHOICES), + required=False, + widget=StaticSelect2() + ) + phase = forms.ChoiceField( + choices=add_blank_choice(POWERFEED_PHASE_CHOICES), + required=False, + widget=StaticSelect2() + ) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index a97ef576b..a8629245f 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -2129,6 +2129,8 @@ class PowerPanelListView(ObjectListView): ).annotate( powerfeed_count=Count('powerfeeds') ) + filter = filters.PowerPanelFilter + filter_form = forms.PowerPanelFilterForm table = tables.PowerPanelTable template_name = 'dcim/powerpanel_list.html' @@ -2175,6 +2177,7 @@ class PowerPanelBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): ).annotate( rack_count=Count('powerfeeds') ) + filter = filters.PowerPanelFilter table = tables.PowerPanelTable default_return_url = 'dcim:powerpanel_list' @@ -2187,8 +2190,8 @@ class PowerFeedListView(ObjectListView): queryset = PowerFeed.objects.select_related( 'power_panel', 'rack' ) - # filter = filters.PowerFeedFilter - # filter_form = forms.PowerFeedFilterForm + filter = filters.PowerFeedFilter + filter_form = forms.PowerFeedFilterForm table = tables.PowerFeedTable template_name = 'dcim/powerfeed_list.html' @@ -2232,7 +2235,7 @@ class PowerFeedBulkImportView(PermissionRequiredMixin, BulkImportView): class PowerFeedBulkEditView(PermissionRequiredMixin, BulkEditView): permission_required = 'dcim.change_powerfeed' queryset = PowerFeed.objects.select_related('power_panel', 'rack') - # filter = filters.PowerFeedFilter + filter = filters.PowerFeedFilter table = tables.PowerFeedTable form = forms.PowerFeedBulkEditForm default_return_url = 'dcim:powerfeed_list' @@ -2241,6 +2244,6 @@ class PowerFeedBulkEditView(PermissionRequiredMixin, BulkEditView): class PowerFeedBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'dcim.delete_powerfeed' queryset = PowerFeed.objects.select_related('power_panel', 'rack') - # filter = filters.PowerFeedFilter + filter = filters.PowerFeedFilter table = tables.PowerFeedTable default_return_url = 'dcim:powerfeed_list' diff --git a/netbox/templates/dcim/powerpanel_list.html b/netbox/templates/dcim/powerpanel_list.html index b58469c12..a0d49b30b 100644 --- a/netbox/templates/dcim/powerpanel_list.html +++ b/netbox/templates/dcim/powerpanel_list.html @@ -11,8 +11,11 @@

{% block title %}Power Panels{% endblock %}

-
+
{% include 'utilities/obj_table.html' with bulk_delete_url='dcim:powerpanel_bulk_delete' %}
+
+ {% include 'inc/search_panel.html' %} +
{% endblock %}