Skip to content

Commit 98cc36c

Browse files
Merge pull request #7824 from netbox-community/2101-q-filters
Closes #2101: Ensure all relevant models have a general purpose search filter
2 parents 1fed564 + f3beabb commit 98cc36c

File tree

5 files changed

+109
-0
lines changed

5 files changed

+109
-0
lines changed

docs/release-notes/version-3.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Enhancements
66

7+
* [#2101](https://github.com/netbox-community/netbox/issues/2101) - Add missing `q` filters for necessary models
78
* [#7803](https://github.com/netbox-community/netbox/issues/7803) - Improve live reloading of custom scripts
89
* [#7810](https://github.com/netbox-community/netbox/issues/7810) - Add IEEE 802.15.1 interface type
910

netbox/dcim/filtersets.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,10 @@ def search(self, queryset, name, value):
13941394
#
13951395

13961396
class ConnectionFilterSet(BaseFilterSet):
1397+
q = django_filters.CharFilter(
1398+
method='search',
1399+
label='Search',
1400+
)
13971401
site_id = MultiValueNumberFilter(
13981402
method='filter_connections',
13991403
field_name='device__site_id'
@@ -1416,6 +1420,15 @@ def filter_connections(self, queryset, name, value):
14161420
return queryset
14171421
return queryset.filter(**{f'{name}__in': value})
14181422

1423+
def search(self, queryset, name, value):
1424+
if not value.strip():
1425+
return queryset
1426+
qs_filter = (
1427+
Q(device__name__icontains=value) |
1428+
Q(cable__label__icontains=value)
1429+
)
1430+
return queryset.filter(qs_filter)
1431+
14191432

14201433
class ConsoleConnectionFilterSet(ConnectionFilterSet):
14211434

netbox/dcim/forms/filtersets.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,11 @@ class InventoryItemFilterForm(DeviceComponentFilterForm):
10681068
#
10691069

10701070
class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
1071+
q = forms.CharField(
1072+
required=False,
1073+
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
1074+
label=_('Search')
1075+
)
10711076
region_id = DynamicModelMultipleChoiceField(
10721077
queryset=Region.objects.all(),
10731078
required=False,
@@ -1095,6 +1100,11 @@ class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form):
10951100

10961101

10971102
class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
1103+
q = forms.CharField(
1104+
required=False,
1105+
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
1106+
label=_('Search')
1107+
)
10981108
region_id = DynamicModelMultipleChoiceField(
10991109
queryset=Region.objects.all(),
11001110
required=False,
@@ -1122,6 +1132,11 @@ class PowerConnectionFilterForm(BootstrapMixin, forms.Form):
11221132

11231133

11241134
class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form):
1135+
q = forms.CharField(
1136+
required=False,
1137+
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
1138+
label=_('Search')
1139+
)
11251140
region_id = DynamicModelMultipleChoiceField(
11261141
queryset=Region.objects.all(),
11271142
required=False,

netbox/extras/filtersets.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636

3737
class WebhookFilterSet(BaseFilterSet):
38+
q = django_filters.CharFilter(
39+
method='search',
40+
label='Search',
41+
)
3842
content_types = ContentTypeFilter()
3943
http_method = django_filters.MultipleChoiceFilter(
4044
choices=WebhookHttpMethodChoices
@@ -47,37 +51,93 @@ class Meta:
4751
'http_method', 'http_content_type', 'secret', 'ssl_verification', 'ca_file_path',
4852
]
4953

54+
def search(self, queryset, name, value):
55+
if not value.strip():
56+
return queryset
57+
return queryset.filter(
58+
Q(name__icontains=value) |
59+
Q(payload_url__icontains=value)
60+
)
61+
5062

5163
class CustomFieldFilterSet(BaseFilterSet):
64+
q = django_filters.CharFilter(
65+
method='search',
66+
label='Search',
67+
)
5268
content_types = ContentTypeFilter()
5369

5470
class Meta:
5571
model = CustomField
5672
fields = ['id', 'content_types', 'name', 'required', 'filter_logic', 'weight']
5773

74+
def search(self, queryset, name, value):
75+
if not value.strip():
76+
return queryset
77+
return queryset.filter(
78+
Q(name__icontains=value) |
79+
Q(label__icontains=value) |
80+
Q(description__icontains=value)
81+
)
82+
5883

5984
class CustomLinkFilterSet(BaseFilterSet):
85+
q = django_filters.CharFilter(
86+
method='search',
87+
label='Search',
88+
)
6089

6190
class Meta:
6291
model = CustomLink
6392
fields = ['id', 'content_type', 'name', 'link_text', 'link_url', 'weight', 'group_name', 'new_window']
6493

94+
def search(self, queryset, name, value):
95+
if not value.strip():
96+
return queryset
97+
return queryset.filter(
98+
Q(name__icontains=value) |
99+
Q(link_text__icontains=value) |
100+
Q(link_url__icontains=value) |
101+
Q(group_name__icontains=value)
102+
)
103+
65104

66105
class ExportTemplateFilterSet(BaseFilterSet):
106+
q = django_filters.CharFilter(
107+
method='search',
108+
label='Search',
109+
)
67110

68111
class Meta:
69112
model = ExportTemplate
70113
fields = ['id', 'content_type', 'name']
71114

115+
def search(self, queryset, name, value):
116+
if not value.strip():
117+
return queryset
118+
return queryset.filter(
119+
Q(name__icontains=value) |
120+
Q(description__icontains=value)
121+
)
122+
72123

73124
class ImageAttachmentFilterSet(BaseFilterSet):
125+
q = django_filters.CharFilter(
126+
method='search',
127+
label='Search',
128+
)
74129
created = django_filters.DateTimeFilter()
75130
content_type = ContentTypeFilter()
76131

77132
class Meta:
78133
model = ImageAttachment
79134
fields = ['id', 'content_type_id', 'object_id', 'name']
80135

136+
def search(self, queryset, name, value):
137+
if not value.strip():
138+
return queryset
139+
return queryset.filter(name__icontains=value)
140+
81141

82142
class JournalEntryFilterSet(ChangeLoggedModelFilterSet):
83143
q = django_filters.CharFilter(

netbox/users/filtersets.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,20 @@ class Meta:
9999
model = Token
100100
fields = ['id', 'key', 'write_enabled']
101101

102+
def search(self, queryset, name, value):
103+
if not value.strip():
104+
return queryset
105+
return queryset.filter(
106+
Q(user__username__icontains=value) |
107+
Q(description__icontains=value)
108+
)
109+
102110

103111
class ObjectPermissionFilterSet(BaseFilterSet):
112+
q = django_filters.CharFilter(
113+
method='search',
114+
label='Search',
115+
)
104116
user_id = django_filters.ModelMultipleChoiceFilter(
105117
field_name='users',
106118
queryset=User.objects.all(),
@@ -127,3 +139,11 @@ class ObjectPermissionFilterSet(BaseFilterSet):
127139
class Meta:
128140
model = ObjectPermission
129141
fields = ['id', 'name', 'enabled', 'object_types']
142+
143+
def search(self, queryset, name, value):
144+
if not value.strip():
145+
return queryset
146+
return queryset.filter(
147+
Q(name__icontains=value) |
148+
Q(description__icontains=value)
149+
)

0 commit comments

Comments
 (0)