Ver Fonte

Add missing filters

Jeremy Stretch há 1 ano atrás
pai
commit
16b422cbac

+ 19 - 2
netbox/circuits/filtersets.py

@@ -158,6 +158,12 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
         queryset=ProviderAccount.objects.all(),
         label=_('Provider account (ID)'),
     )
+    provider_account = django_filters.ModelMultipleChoiceFilter(
+        field_name='provider_account__account',
+        queryset=Provider.objects.all(),
+        to_field_name='account',
+        label=_('Provider account (account)'),
+    )
     provider_network_id = django_filters.ModelMultipleChoiceFilter(
         field_name='terminations__provider_network',
         queryset=ProviderNetwork.objects.all(),
@@ -214,10 +220,18 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
         to_field_name='slug',
         label=_('Site (slug)'),
     )
+    termination_a_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=CircuitTermination.objects.all(),
+        label=_('Termination A (ID)'),
+    )
+    termination_z_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=CircuitTermination.objects.all(),
+        label=_('Termination A (ID)'),
+    )
 
     class Meta:
         model = Circuit
-        fields = ['id', 'cid', 'description', 'install_date', 'termination_date', 'commit_rate']
+        fields = ('id', 'cid', 'description', 'install_date', 'termination_date', 'commit_rate')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -258,7 +272,10 @@ class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet):
 
     class Meta:
         model = CircuitTermination
-        fields = ['id', 'term_side', 'port_speed', 'upstream_speed', 'xconnect_id', 'description', 'cable_end']
+        fields = (
+            'id', 'term_side', 'port_speed', 'upstream_speed', 'xconnect_id', 'description', 'mark_connected',
+            'pp_info', 'cable_end',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 3 - 5
netbox/core/filtersets.py

@@ -28,7 +28,7 @@ class DataSourceFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = DataSource
-        fields = ('id', 'name', 'enabled', 'description')
+        fields = ('id', 'name', 'enabled', 'description', 'source_url', 'last_synced')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -115,7 +115,7 @@ class JobFilterSet(BaseFilterSet):
 
     class Meta:
         model = Job
-        fields = ('id', 'object_type', 'object_id', 'name', 'interval', 'status', 'user')
+        fields = ('id', 'object_type', 'object_id', 'name', 'interval', 'status', 'user', 'job_id')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -134,9 +134,7 @@ class ConfigRevisionFilterSet(BaseFilterSet):
 
     class Meta:
         model = ConfigRevision
-        fields = [
-            'id',
-        ]
+        fields = ('id', 'created', 'comment')
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 106 - 41
netbox/dcim/filtersets.py

@@ -18,7 +18,7 @@ from tenancy.models import *
 from utilities.choices import ColorChoices
 from utilities.filters import (
     ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
-    TreeNodeMultipleChoiceFilter,
+    NumericArrayFilter, TreeNodeMultipleChoiceFilter,
 )
 from virtualization.models import Cluster
 from vpn.models import L2VPN
@@ -178,12 +178,11 @@ class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
         queryset=ASN.objects.all(),
         label=_('AS (ID)'),
     )
+    time_zone = MultiValueCharFilter()
 
     class Meta:
         model = Site
-        fields = (
-            'id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description'
-        )
+        fields = ('id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -447,10 +446,14 @@ class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
         to_field_name='username',
         label=_('User (name)'),
     )
+    unit = NumericArrayFilter(
+        field_name='units',
+        lookup_expr='contains'
+    )
 
     class Meta:
         model = RackReservation
-        fields = ['id', 'created', 'description']
+        fields = ('id', 'created', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -538,10 +541,22 @@ class DeviceTypeFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = DeviceType
-        fields = [
+        fields = (
             'id', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization', 'is_full_depth',
             'subdevice_role', 'airflow', 'weight', 'weight_unit', 'description',
-        ]
+
+            # Counters
+            'console_port_template_count',
+            'console_server_port_template_count',
+            'power_port_template_count',
+            'power_outlet_template_count',
+            'interface_template_count',
+            'front_port_template_count',
+            'rear_port_template_count',
+            'device_bay_template_count',
+            'module_bay_template_count',
+            'inventory_item_template_count',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -675,12 +690,15 @@ class DeviceTypeComponentFilterSet(django_filters.FilterSet):
         method='search',
         label=_('Search'),
     )
-    devicetype_id = django_filters.ModelMultipleChoiceFilter(
+    device_type_id = django_filters.ModelMultipleChoiceFilter(
         queryset=DeviceType.objects.all(),
         field_name='device_type_id',
         label=_('Device type (ID)'),
     )
 
+    # TODO: Remove in v4.1
+    devicetype_id = device_type_id
+
     def search(self, queryset, name, value):
         if not value.strip():
             return queryset
@@ -691,32 +709,35 @@ class DeviceTypeComponentFilterSet(django_filters.FilterSet):
 
 
 class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
-    moduletype_id = django_filters.ModelMultipleChoiceFilter(
+    module_type_id = django_filters.ModelMultipleChoiceFilter(
         queryset=ModuleType.objects.all(),
         field_name='module_type_id',
         label=_('Module type (ID)'),
     )
 
+    # TODO: Remove in v4.1
+    moduletype_id = module_type_id
+
 
 class ConsolePortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
 
     class Meta:
         model = ConsolePortTemplate
-        fields = ['id', 'name', 'type', 'description']
+        fields = ('id', 'name', 'label', 'type', 'description')
 
 
 class ConsoleServerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
 
     class Meta:
         model = ConsoleServerPortTemplate
-        fields = ['id', 'name', 'type', 'description']
+        fields = ('id', 'name', 'label', 'type', 'description')
 
 
 class PowerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
 
     class Meta:
         model = PowerPortTemplate
-        fields = ['id', 'name', 'type', 'maximum_draw', 'allocated_draw', 'description']
+        fields = ('id', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
 
 
 class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
@@ -724,10 +745,14 @@ class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceType
         choices=PowerOutletFeedLegChoices,
         null_value=None
     )
+    power_port_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=PowerPortTemplate.objects.all(),
+        label=_('Power port (ID)'),
+    )
 
     class Meta:
         model = PowerOutletTemplate
-        fields = ['id', 'name', 'type', 'feed_leg', 'description']
+        fields = ('id', 'name', 'label', 'type', 'feed_leg', 'description')
 
 
 class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
@@ -751,7 +776,7 @@ class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeCo
 
     class Meta:
         model = InterfaceTemplate
-        fields = ['id', 'name', 'type', 'enabled', 'mgmt_only', 'description']
+        fields = ('id', 'name', 'label', 'type', 'enabled', 'mgmt_only', 'description')
 
 
 class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
@@ -762,7 +787,7 @@ class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeCo
 
     class Meta:
         model = FrontPortTemplate
-        fields = ['id', 'name', 'type', 'color', 'description']
+        fields = ('id', 'name', 'label', 'type', 'color', 'rear_port_id', 'rear_port_position', 'description')
 
 
 class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
@@ -773,21 +798,21 @@ class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeCom
 
     class Meta:
         model = RearPortTemplate
-        fields = ['id', 'name', 'type', 'color', 'positions', 'description']
+        fields = ('id', 'name', 'label', 'type', 'color', 'positions', 'description')
 
 
 class ModuleBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
 
     class Meta:
         model = ModuleBayTemplate
-        fields = ['id', 'name', 'description']
+        fields = ('id', 'name', 'label', 'position', 'description')
 
 
 class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
 
     class Meta:
         model = DeviceBayTemplate
-        fields = ['id', 'name', 'description']
+        fields = ('id', 'name', 'label', 'description')
 
 
 class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
@@ -1068,10 +1093,22 @@ class DeviceFilterSet(
 
     class Meta:
         model = Device
-        fields = [
+        fields = (
             'id', 'asset_tag', 'face', 'position', 'latitude', 'longitude', 'airflow', 'vc_position', 'vc_priority',
             'description',
-        ]
+
+            # Counters
+            'console_port_count',
+            'console_server_port_count',
+            'power_port_count',
+            'power_outlet_count',
+            'interface_count',
+            'front_port_count',
+            'rear_port_count',
+            'device_bay_count',
+            'module_bay_count',
+            'inventory_item_count',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1151,7 +1188,7 @@ class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, Prim
 
     class Meta:
         model = VirtualDeviceContext
-        fields = ['id', 'device', 'name', 'description']
+        fields = ('id', 'device', 'name', 'identifier', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1217,7 +1254,7 @@ class ModuleFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = Module
-        fields = ['id', 'status', 'asset_tag', 'description']
+        fields = ('id', 'status', 'asset_tag', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1361,6 +1398,10 @@ class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
 
 
 class CabledObjectFilterSet(django_filters.FilterSet):
+    cable_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=Cable.objects.all(),
+        label=_('Cable (ID)'),
+    )
     cabled = django_filters.BooleanFilter(
         field_name='cable',
         lookup_expr='isnull',
@@ -1402,7 +1443,7 @@ class ConsolePortFilterSet(
 
     class Meta:
         model = ConsolePort
-        fields = ['id', 'name', 'label', 'description', 'cable_end']
+        fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
 
 
 class ConsoleServerPortFilterSet(
@@ -1418,7 +1459,7 @@ class ConsoleServerPortFilterSet(
 
     class Meta:
         model = ConsoleServerPort
-        fields = ['id', 'name', 'label', 'description', 'cable_end']
+        fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
 
 
 class PowerPortFilterSet(
@@ -1434,7 +1475,9 @@ class PowerPortFilterSet(
 
     class Meta:
         model = PowerPort
-        fields = ['id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description', 'cable_end']
+        fields = (
+            'id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable_end',
+        )
 
 
 class PowerOutletFilterSet(
@@ -1451,10 +1494,16 @@ class PowerOutletFilterSet(
         choices=PowerOutletFeedLegChoices,
         null_value=None
     )
+    power_port_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=PowerPort.objects.all(),
+        label=_('Power port (ID)'),
+    )
 
     class Meta:
         model = PowerOutlet
-        fields = ['id', 'name', 'label', 'feed_leg', 'description', 'cable_end']
+        fields = (
+            'id', 'name', 'label', 'feed_leg', 'description', 'mark_connected', 'cable_end',
+        )
 
 
 class CommonInterfaceFilterSet(django_filters.FilterSet):
@@ -1586,10 +1635,11 @@ class InterfaceFilterSet(
 
     class Meta:
         model = Interface
-        fields = [
+        fields = (
             'id', 'name', 'label', 'type', 'enabled', 'mtu', 'mgmt_only', 'poe_mode', 'poe_type', 'mode', 'rf_role',
-            'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'cable_end',
-        ]
+            'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected',
+            'cable_id', 'cable_end', 'wireless_link_id',
+        )
 
     def filter_virtual_chassis_member(self, queryset, name, value):
         try:
@@ -1621,7 +1671,10 @@ class FrontPortFilterSet(
 
     class Meta:
         model = FrontPort
-        fields = ['id', 'name', 'label', 'type', 'color', 'description', 'cable_end']
+        fields = (
+            'id', 'name', 'label', 'type', 'color', 'rear_port_id', 'rear_port_position', 'description',
+            'mark_connected', 'cable_end',
+        )
 
 
 class RearPortFilterSet(
@@ -1636,21 +1689,33 @@ class RearPortFilterSet(
 
     class Meta:
         model = RearPort
-        fields = ['id', 'name', 'label', 'type', 'color', 'positions', 'description', 'cable_end']
+        fields = (
+            'id', 'name', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable_end',
+        )
 
 
 class ModuleBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
 
     class Meta:
         model = ModuleBay
-        fields = ['id', 'name', 'label', 'description']
+        fields = ('id', 'name', 'label', 'position', 'description')
 
 
 class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
+    installed_device_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=Device.objects.all(),
+        label=_('Installed device (ID)'),
+    )
+    installed_device = django_filters.ModelMultipleChoiceFilter(
+        field_name='installed_device__name',
+        queryset=Device.objects.all(),
+        to_field_name='name',
+        label=_('Installed device (name)'),
+    )
 
     class Meta:
         model = DeviceBay
-        fields = ['id', 'name', 'label', 'description']
+        fields = ('id', 'name', 'label', 'description')
 
 
 class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
@@ -1686,7 +1751,7 @@ class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
 
     class Meta:
         model = InventoryItem
-        fields = ['id', 'name', 'label', 'part_id', 'asset_tag', 'discovered']
+        fields = ('id', 'name', 'label', 'part_id', 'asset_tag', 'description', 'discovered')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1770,7 +1835,7 @@ class VirtualChassisFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = VirtualChassis
-        fields = ['id', 'domain', 'name', 'description']
+        fields = ('id', 'domain', 'name', 'description', 'member_count')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1953,12 +2018,12 @@ class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
         return self.filter_by_termination_object(queryset, CircuitTermination, value)
 
 
-class CableTerminationFilterSet(BaseFilterSet):
+class CableTerminationFilterSet(ChangeLoggedModelFilterSet):
     termination_type = ContentTypeFilter()
 
     class Meta:
         model = CableTermination
-        fields = ['id', 'cable', 'cable_end', 'termination_type', 'termination_id']
+        fields = ('id', 'cable', 'cable_end', 'termination_type', 'termination_id')
 
 
 class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
@@ -2073,10 +2138,10 @@ class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpoi
 
     class Meta:
         model = PowerFeed
-        fields = [
-            'id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', 'cable_end',
-            'description',
-        ]
+        fields = (
+            'id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization',
+            'available_power', 'mark_connected', 'cable_end', 'description',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 37 - 32
netbox/extras/filtersets.py

@@ -40,12 +40,14 @@ class ScriptFilterSet(BaseFilterSet):
         method='search',
         label=_('Search'),
     )
+    module_id = django_filters.ModelMultipleChoiceFilter(
+        queryset=ScriptModule.objects.all(),
+        label=_('Script module (ID)'),
+    )
 
     class Meta:
         model = Script
-        fields = [
-            'id', 'name',
-        ]
+        fields = ('id', 'name', 'is_executable')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -69,10 +71,10 @@ class WebhookFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = Webhook
-        fields = [
+        fields = (
             'id', 'name', 'payload_url', 'http_method', 'http_content_type', 'secret', 'ssl_verification',
             'ca_file_path', 'description',
-        ]
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -103,10 +105,10 @@ class EventRuleFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = EventRule
-        fields = [
+        fields = (
             'id', 'name', 'type_create', 'type_update', 'type_delete', 'type_job_start', 'type_job_end', 'enabled',
             'action_type', 'description',
-        ]
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -118,7 +120,7 @@ class EventRuleFilterSet(NetBoxModelFilterSet):
         )
 
 
-class CustomFieldFilterSet(BaseFilterSet):
+class CustomFieldFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -147,10 +149,11 @@ class CustomFieldFilterSet(BaseFilterSet):
 
     class Meta:
         model = CustomField
-        fields = [
-            'id', 'name', 'group_name', 'required', 'search_weight', 'filter_logic', 'ui_visible', 'ui_editable',
-            'weight', 'is_cloneable', 'description',
-        ]
+        fields = (
+            'id', 'name', 'label', 'group_name', 'required', 'search_weight', 'filter_logic', 'ui_visible',
+            'ui_editable', 'weight', 'is_cloneable', 'description', 'validation_minimum', 'validation_maximum',
+            'validation_regex',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -163,7 +166,7 @@ class CustomFieldFilterSet(BaseFilterSet):
         )
 
 
-class CustomFieldChoiceSetFilterSet(BaseFilterSet):
+class CustomFieldChoiceSetFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -174,9 +177,9 @@ class CustomFieldChoiceSetFilterSet(BaseFilterSet):
 
     class Meta:
         model = CustomFieldChoiceSet
-        fields = [
+        fields = (
             'id', 'name', 'description', 'base_choices', 'order_alphabetically',
-        ]
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -191,7 +194,7 @@ class CustomFieldChoiceSetFilterSet(BaseFilterSet):
         return queryset.filter(extra_choices__overlap=value)
 
 
-class CustomLinkFilterSet(BaseFilterSet):
+class CustomLinkFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -205,9 +208,9 @@ class CustomLinkFilterSet(BaseFilterSet):
 
     class Meta:
         model = CustomLink
-        fields = [
-            'id', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'new_window',
-        ]
+        fields = (
+            'id', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'new_window', 'button_class',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -220,7 +223,7 @@ class CustomLinkFilterSet(BaseFilterSet):
         )
 
 
-class ExportTemplateFilterSet(BaseFilterSet):
+class ExportTemplateFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -242,7 +245,10 @@ class ExportTemplateFilterSet(BaseFilterSet):
 
     class Meta:
         model = ExportTemplate
-        fields = ['id', 'name', 'description', 'data_synced']
+        fields = (
+            'id', 'name', 'description', 'mime_type', 'file_extension', 'as_attachment', 'auto_sync_enabled',
+            'data_synced',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -253,7 +259,7 @@ class ExportTemplateFilterSet(BaseFilterSet):
         )
 
 
-class SavedFilterFilterSet(BaseFilterSet):
+class SavedFilterFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -280,7 +286,7 @@ class SavedFilterFilterSet(BaseFilterSet):
 
     class Meta:
         model = SavedFilter
-        fields = ['id', 'name', 'slug', 'description', 'enabled', 'shared', 'weight']
+        fields = ('id', 'name', 'slug', 'description', 'enabled', 'shared', 'weight')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -324,17 +330,16 @@ class BookmarkFilterSet(BaseFilterSet):
         fields = ['id', 'object_id']
 
 
-class ImageAttachmentFilterSet(BaseFilterSet):
+class ImageAttachmentFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
     )
-    created = django_filters.DateTimeFilter()
     object_type = ContentTypeFilter()
 
     class Meta:
         model = ImageAttachment
-        fields = ['id', 'object_type_id', 'object_id', 'name']
+        fields = ('id', 'object_type_id', 'object_id', 'name', 'image_width', 'image_height')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -579,7 +584,7 @@ class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
 
     class Meta:
         model = ConfigContext
-        fields = ['id', 'name', 'is_active', 'data_synced', 'description']
+        fields = ('id', 'name', 'is_active', 'description', 'weight', 'auto_sync_enabled', 'data_synced')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -591,7 +596,7 @@ class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
         )
 
 
-class ConfigTemplateFilterSet(BaseFilterSet):
+class ConfigTemplateFilterSet(ChangeLoggedModelFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label=_('Search'),
@@ -608,7 +613,7 @@ class ConfigTemplateFilterSet(BaseFilterSet):
 
     class Meta:
         model = ConfigTemplate
-        fields = ['id', 'name', 'description', 'data_synced']
+        fields = ('id', 'name', 'description', 'auto_sync_enabled', 'data_synced')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -656,10 +661,10 @@ class ObjectChangeFilterSet(BaseFilterSet):
 
     class Meta:
         model = ObjectChange
-        fields = [
+        fields = (
             'id', 'user', 'user_name', 'request_id', 'action', 'changed_object_type_id', 'changed_object_id',
-            'object_repr',
-        ]
+            'related_object_type', 'related_object_id', 'object_repr',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 6 - 7
netbox/ipam/filtersets.py

@@ -183,7 +183,7 @@ class ASNRangeFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
 
     class Meta:
         model = ASNRange
-        fields = ['id', 'name', 'start', 'end', 'description']
+        fields = ('id', 'name', 'slug', 'start', 'end', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -234,7 +234,7 @@ class RoleFilterSet(OrganizationalModelFilterSet):
 
     class Meta:
         model = Role
-        fields = ['id', 'name', 'slug', 'description']
+        fields = ('id', 'name', 'slug', 'description', 'weight')
 
 
 class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
@@ -475,7 +475,7 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
 
     class Meta:
         model = IPRange
-        fields = ['id', 'mark_utilized', 'description']
+        fields = ('id', 'mark_utilized', 'size', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -631,7 +631,7 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
 
     class Meta:
         model = IPAddress
-        fields = ['id', 'dns_name', 'description']
+        fields = ('id', 'dns_name', 'description', 'assigned_object_type', 'assigned_object_id', 'nat_inside_id')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1008,7 +1008,7 @@ class ServiceTemplateFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = ServiceTemplate
-        fields = ['id', 'name', 'protocol', 'description']
+        fields = ('id', 'name', 'protocol', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1052,7 +1052,6 @@ class ServiceFilterSet(NetBoxModelFilterSet):
         to_field_name='address',
         label=_('IP address'),
     )
-
     port = NumericArrayFilter(
         field_name='ports',
         lookup_expr='contains'
@@ -1060,7 +1059,7 @@ class ServiceFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = Service
-        fields = ['id', 'name', 'protocol', 'description']
+        fields = ('id', 'name', 'protocol', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 7 - 4
netbox/users/filtersets.py

@@ -22,7 +22,7 @@ class GroupFilterSet(BaseFilterSet):
 
     class Meta:
         model = Group
-        fields = ['id', 'name']
+        fields = ('id', 'name', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -49,7 +49,10 @@ class UserFilterSet(BaseFilterSet):
 
     class Meta:
         model = get_user_model()
-        fields = ['id', 'username', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'is_superuser']
+        fields = (
+            'id', 'username', 'first_name', 'last_name', 'email', 'date_joined', 'last_login', 'is_staff', 'is_active',
+            'is_superuser',
+        )
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -99,7 +102,7 @@ class TokenFilterSet(BaseFilterSet):
 
     class Meta:
         model = Token
-        fields = ['id', 'key', 'write_enabled', 'description']
+        fields = ('id', 'key', 'write_enabled', 'description', 'last_used')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -152,7 +155,7 @@ class ObjectPermissionFilterSet(BaseFilterSet):
 
     class Meta:
         model = ObjectPermission
-        fields = ['id', 'name', 'enabled', 'object_types', 'description']
+        fields = ('id', 'name', 'enabled', 'object_types', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 2 - 2
netbox/virtualization/filtersets.py

@@ -240,7 +240,7 @@ class VirtualMachineFilterSet(
 
     class Meta:
         model = VirtualMachine
-        fields = ['id', 'cluster', 'vcpus', 'memory', 'disk', 'description']
+        fields = ('id', 'cluster', 'vcpus', 'memory', 'disk', 'description', 'interface_count', 'virtual_disk_count')
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -299,7 +299,7 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet):
 
     class Meta:
         model = VMInterface
-        fields = ['id', 'name', 'enabled', 'mtu', 'description']
+        fields = ('id', 'name', 'enabled', 'mtu', 'mode', 'description')
 
     def search(self, queryset, name, value):
         if not value.strip():

+ 2 - 2
netbox/vpn/filtersets.py

@@ -120,7 +120,7 @@ class TunnelTerminationFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = TunnelTermination
-        fields = ['id']
+        fields = ('id', 'termination_id')
 
 
 class IKEProposalFilterSet(NetBoxModelFilterSet):
@@ -402,7 +402,7 @@ class L2VPNTerminationFilterSet(NetBoxModelFilterSet):
 
     class Meta:
         model = L2VPNTermination
-        fields = ('id', 'assigned_object_type_id')
+        fields = ('id', 'assigned_object_id')
 
     def search(self, queryset, name, value):
         if not value.strip():