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

Fixes #16779: Fix saved filter selection for child object lists (#16789)

* Fixes #16779: Fix saved filter selection for child object lists

* Omit label_suffix
Jeremy Stretch 1 год назад
Родитель
Сommit
b18a6b7c59

+ 15 - 0
netbox/dcim/views.py

@@ -31,6 +31,7 @@ from utilities.views import (
     GetRelatedModelsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view
 )
 from virtualization.filtersets import VirtualMachineFilterSet
+from virtualization.forms import VirtualMachineFilterForm
 from virtualization.models import VirtualMachine
 from virtualization.tables import VirtualMachineTable
 from . import filtersets, forms, tables
@@ -679,6 +680,7 @@ class RackRackReservationsView(generic.ObjectChildrenView):
     child_model = RackReservation
     table = tables.RackReservationTable
     filterset = filtersets.RackReservationFilterSet
+    filterset_form = forms.RackReservationFilterForm
     template_name = 'dcim/rack/reservations.html'
     tab = ViewTab(
         label=_('Reservations'),
@@ -697,6 +699,7 @@ class RackNonRackedView(generic.ObjectChildrenView):
     child_model = Device
     table = tables.DeviceTable
     filterset = filtersets.DeviceFilterSet
+    filterset_form = forms.DeviceFilterForm
     template_name = 'dcim/rack/non_racked_devices.html'
     tab = ViewTab(
         label=_('Non-Racked Devices'),
@@ -1835,6 +1838,7 @@ class DeviceConsolePortsView(DeviceComponentsView):
     child_model = ConsolePort
     table = tables.DeviceConsolePortTable
     filterset = filtersets.ConsolePortFilterSet
+    filterset_form = forms.ConsolePortFilterForm
     template_name = 'dcim/device/consoleports.html',
     tab = ViewTab(
         label=_('Console Ports'),
@@ -1850,6 +1854,7 @@ class DeviceConsoleServerPortsView(DeviceComponentsView):
     child_model = ConsoleServerPort
     table = tables.DeviceConsoleServerPortTable
     filterset = filtersets.ConsoleServerPortFilterSet
+    filterset_form = forms.ConsoleServerPortFilterForm
     template_name = 'dcim/device/consoleserverports.html'
     tab = ViewTab(
         label=_('Console Server Ports'),
@@ -1865,6 +1870,7 @@ class DevicePowerPortsView(DeviceComponentsView):
     child_model = PowerPort
     table = tables.DevicePowerPortTable
     filterset = filtersets.PowerPortFilterSet
+    filterset_form = forms.PowerPortFilterForm
     template_name = 'dcim/device/powerports.html'
     tab = ViewTab(
         label=_('Power Ports'),
@@ -1880,6 +1886,7 @@ class DevicePowerOutletsView(DeviceComponentsView):
     child_model = PowerOutlet
     table = tables.DevicePowerOutletTable
     filterset = filtersets.PowerOutletFilterSet
+    filterset_form = forms.PowerOutletFilterForm
     template_name = 'dcim/device/poweroutlets.html'
     tab = ViewTab(
         label=_('Power Outlets'),
@@ -1895,6 +1902,7 @@ class DeviceInterfacesView(DeviceComponentsView):
     child_model = Interface
     table = tables.DeviceInterfaceTable
     filterset = filtersets.InterfaceFilterSet
+    filterset_form = forms.InterfaceFilterForm
     template_name = 'dcim/device/interfaces.html'
     tab = ViewTab(
         label=_('Interfaces'),
@@ -1916,6 +1924,7 @@ class DeviceFrontPortsView(DeviceComponentsView):
     child_model = FrontPort
     table = tables.DeviceFrontPortTable
     filterset = filtersets.FrontPortFilterSet
+    filterset_form = forms.FrontPortFilterForm
     template_name = 'dcim/device/frontports.html'
     tab = ViewTab(
         label=_('Front Ports'),
@@ -1931,6 +1940,7 @@ class DeviceRearPortsView(DeviceComponentsView):
     child_model = RearPort
     table = tables.DeviceRearPortTable
     filterset = filtersets.RearPortFilterSet
+    filterset_form = forms.RearPortFilterForm
     template_name = 'dcim/device/rearports.html'
     tab = ViewTab(
         label=_('Rear Ports'),
@@ -1946,6 +1956,7 @@ class DeviceModuleBaysView(DeviceComponentsView):
     child_model = ModuleBay
     table = tables.DeviceModuleBayTable
     filterset = filtersets.ModuleBayFilterSet
+    filterset_form = forms.ModuleBayFilterForm
     template_name = 'dcim/device/modulebays.html'
     actions = {
         **DEFAULT_ACTION_PERMISSIONS,
@@ -1965,6 +1976,7 @@ class DeviceDeviceBaysView(DeviceComponentsView):
     child_model = DeviceBay
     table = tables.DeviceDeviceBayTable
     filterset = filtersets.DeviceBayFilterSet
+    filterset_form = forms.DeviceBayFilterForm
     template_name = 'dcim/device/devicebays.html'
     actions = {
         **DEFAULT_ACTION_PERMISSIONS,
@@ -1984,6 +1996,7 @@ class DeviceInventoryView(DeviceComponentsView):
     child_model = InventoryItem
     table = tables.DeviceInventoryItemTable
     filterset = filtersets.InventoryItemFilterSet
+    filterset_form = forms.InventoryItemFilterForm
     template_name = 'dcim/device/inventory.html'
     actions = {
         **DEFAULT_ACTION_PERMISSIONS,
@@ -2062,6 +2075,7 @@ class DeviceVirtualMachinesView(generic.ObjectChildrenView):
     child_model = VirtualMachine
     table = VirtualMachineTable
     filterset = VirtualMachineFilterSet
+    filterset_form = VirtualMachineFilterForm
     tab = ViewTab(
         label=_('Virtual Machines'),
         badge=lambda obj: VirtualMachine.objects.filter(cluster=obj.cluster, device=obj).count(),
@@ -2944,6 +2958,7 @@ class InventoryItemChildrenView(generic.ObjectChildrenView):
     child_model = InventoryItem
     table = tables.InventoryItemTable
     filterset = filtersets.InventoryItemFilterSet
+    filterset_form = forms.InventoryItemFilterForm
     tab = ViewTab(
         label=_('Children'),
         badge=lambda obj: obj.child_items.count(),

+ 12 - 0
netbox/ipam/views.py

@@ -7,6 +7,7 @@ from django.utils.translation import gettext as _
 
 from circuits.models import Provider
 from dcim.filtersets import InterfaceFilterSet
+from dcim.forms import InterfaceFilterForm
 from dcim.models import Interface, Site
 from netbox.views import generic
 from tenancy.views import ObjectContactsView
@@ -14,6 +15,7 @@ from utilities.query import count_related
 from utilities.tables import get_table_ordering
 from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
 from virtualization.filtersets import VMInterfaceFilterSet
+from virtualization.forms import VMInterfaceFilterForm
 from virtualization.models import VMInterface
 from . import filtersets, forms, tables
 from .choices import PrefixStatusChoices
@@ -206,6 +208,7 @@ class ASNRangeASNsView(generic.ObjectChildrenView):
     child_model = ASN
     table = tables.ASNTable
     filterset = filtersets.ASNFilterSet
+    filterset_form = forms.ASNFilterForm
     tab = ViewTab(
         label=_('ASNs'),
         badge=lambda x: x.get_child_asns().count(),
@@ -337,6 +340,7 @@ class AggregatePrefixesView(generic.ObjectChildrenView):
     child_model = Prefix
     table = tables.PrefixTable
     filterset = filtersets.PrefixFilterSet
+    filterset_form = forms.PrefixFilterForm
     template_name = 'ipam/aggregate/prefixes.html'
     tab = ViewTab(
         label=_('Prefixes'),
@@ -523,6 +527,7 @@ class PrefixPrefixesView(generic.ObjectChildrenView):
     child_model = Prefix
     table = tables.PrefixTable
     filterset = filtersets.PrefixFilterSet
+    filterset_form = forms.PrefixFilterForm
     template_name = 'ipam/prefix/prefixes.html'
     tab = ViewTab(
         label=_('Child Prefixes'),
@@ -558,6 +563,7 @@ class PrefixIPRangesView(generic.ObjectChildrenView):
     child_model = IPRange
     table = tables.IPRangeTable
     filterset = filtersets.IPRangeFilterSet
+    filterset_form = forms.IPRangeFilterForm
     template_name = 'ipam/prefix/ip_ranges.html'
     tab = ViewTab(
         label=_('Child Ranges'),
@@ -584,6 +590,7 @@ class PrefixIPAddressesView(generic.ObjectChildrenView):
     child_model = IPAddress
     table = tables.IPAddressTable
     filterset = filtersets.IPAddressFilterSet
+    filterset_form = forms.IPAddressFilterForm
     template_name = 'ipam/prefix/ip_addresses.html'
     tab = ViewTab(
         label=_('IP Addresses'),
@@ -683,6 +690,7 @@ class IPRangeIPAddressesView(generic.ObjectChildrenView):
     child_model = IPAddress
     table = tables.IPAddressTable
     filterset = filtersets.IPAddressFilterSet
+    filterset_form = forms.IPRangeFilterForm
     template_name = 'ipam/iprange/ip_addresses.html'
     tab = ViewTab(
         label=_('IP Addresses'),
@@ -885,6 +893,7 @@ class IPAddressRelatedIPsView(generic.ObjectChildrenView):
     child_model = IPAddress
     table = tables.IPAddressTable
     filterset = filtersets.IPAddressFilterSet
+    filterset_form = forms.IPAddressFilterForm
     tab = ViewTab(
         label=_('Related IPs'),
         badge=lambda x: x.get_related_ips().count(),
@@ -957,6 +966,7 @@ class VLANGroupVLANsView(generic.ObjectChildrenView):
     child_model = VLAN
     table = tables.VLANTable
     filterset = filtersets.VLANFilterSet
+    filterset_form = forms.VLANFilterForm
     tab = ViewTab(
         label=_('VLANs'),
         badge=lambda x: x.get_child_vlans().count(),
@@ -1112,6 +1122,7 @@ class VLANInterfacesView(generic.ObjectChildrenView):
     child_model = Interface
     table = tables.VLANDevicesTable
     filterset = InterfaceFilterSet
+    filterset_form = InterfaceFilterForm
     tab = ViewTab(
         label=_('Device Interfaces'),
         badge=lambda x: x.get_interfaces().count(),
@@ -1129,6 +1140,7 @@ class VLANVMInterfacesView(generic.ObjectChildrenView):
     child_model = VMInterface
     table = tables.VLANVirtualMachinesTable
     filterset = VMInterfaceFilterSet
+    filterset_form = VMInterfaceFilterForm
     tab = ViewTab(
         label=_('VM Interfaces'),
         badge=lambda x: x.get_vminterfaces().count(),

+ 1 - 1
netbox/netbox/views/generic/bulk_views.py

@@ -176,7 +176,7 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin):
             'model': model,
             'table': table,
             'actions': actions,
-            'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
+            'filter_form': self.filterset_form(request.GET) if self.filterset_form else None,
             'prerequisite_model': get_prerequisite_model(self.queryset),
             **self.get_extra_context(request),
         }

+ 3 - 0
netbox/netbox/views/generic/object_views.py

@@ -87,12 +87,14 @@ class ObjectChildrenView(ObjectView, ActionsMixin, TableMixin):
         child_model: The model class which represents the child objects
         table: The django-tables2 Table class used to render the child objects list
         filterset: A django-filter FilterSet that is applied to the queryset
+        filterset_form: The form class used to render filter options
         actions: A mapping of supported actions to their required permissions. When adding custom actions, bulk
             action names must be prefixed with `bulk_`. (See ActionsMixin.)
     """
     child_model = None
     table = None
     filterset = None
+    filterset_form = None
     template_name = 'generic/object_children.html'
 
     def get_children(self, request, parent):
@@ -152,6 +154,7 @@ class ObjectChildrenView(ObjectView, ActionsMixin, TableMixin):
             'base_template': f'{instance._meta.app_label}/{instance._meta.model_name}.html',
             'table': table,
             'table_config': f'{table.name}_config',
+            'filter_form': self.filterset_form(request.GET) if self.filterset_form else None,
             'actions': actions,
             'tab': self.tab,
             'return_url': request.get_full_path(),

+ 8 - 6
netbox/templates/inc/table_controls_htmx.html

@@ -13,14 +13,16 @@
     </div>
   </div>
 
-  <div class="col-auto d-print-none">
-    <div class="input-group">
-      <div class="input-group-text">
-        <i class="mdi mdi-filter" title="{% trans "Saved filter" %}"></i>
+  {% if filter_form %}
+    <div class="col-auto d-print-none">
+      <div class="input-group">
+        <div class="input-group-text">
+          <i class="mdi mdi-filter" title="{% trans "Saved filter" %}"></i>
+        </div>
+        {{ filter_form.filter_id }}
       </div>
-      {{ filter_form.filter_id }}
     </div>
-  </div>
+  {% endif %}
 
   <div class="col-auto ms-auto d-print-none">
     {% if request.user.is_authenticated and table_modal %}

+ 1 - 0
netbox/tenancy/views.py

@@ -13,6 +13,7 @@ class ObjectContactsView(generic.ObjectChildrenView):
     child_model = ContactAssignment
     table = tables.ContactAssignmentTable
     filterset = filtersets.ContactAssignmentFilterSet
+    filterset_form = forms.ContactAssignmentFilterForm
     template_name = 'tenancy/object_contacts.html'
     tab = ViewTab(
         label=_('Contacts'),

+ 5 - 0
netbox/virtualization/views.py

@@ -10,6 +10,7 @@ from django.utils.translation import gettext as _
 from jinja2.exceptions import TemplateError
 
 from dcim.filtersets import DeviceFilterSet
+from dcim.forms import DeviceFilterForm
 from dcim.models import Device
 from dcim.tables import DeviceTable
 from extras.views import ObjectConfigContextView
@@ -173,6 +174,7 @@ class ClusterVirtualMachinesView(generic.ObjectChildrenView):
     child_model = VirtualMachine
     table = tables.VirtualMachineTable
     filterset = filtersets.VirtualMachineFilterSet
+    filterset_form = forms.VirtualMachineFilterForm
     tab = ViewTab(
         label=_('Virtual Machines'),
         badge=lambda obj: obj.virtual_machines.count(),
@@ -190,6 +192,7 @@ class ClusterDevicesView(generic.ObjectChildrenView):
     child_model = Device
     table = DeviceTable
     filterset = DeviceFilterSet
+    filterset_form = DeviceFilterForm
     template_name = 'virtualization/cluster/devices.html'
     actions = {
         'add': {'add'},
@@ -350,6 +353,7 @@ class VirtualMachineInterfacesView(generic.ObjectChildrenView):
     child_model = VMInterface
     table = tables.VirtualMachineVMInterfaceTable
     filterset = filtersets.VMInterfaceFilterSet
+    filterset_form = forms.VMInterfaceFilterForm
     template_name = 'virtualization/virtualmachine/interfaces.html'
     actions = {
         **DEFAULT_ACTION_PERMISSIONS,
@@ -375,6 +379,7 @@ class VirtualMachineVirtualDisksView(generic.ObjectChildrenView):
     child_model = VirtualDisk
     table = tables.VirtualMachineVirtualDiskTable
     filterset = filtersets.VirtualDiskFilterSet
+    filterset_form = forms.VirtualDiskFilterForm
     template_name = 'virtualization/virtualmachine/virtual_disks.html'
     tab = ViewTab(
         label=_('Virtual Disks'),