mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Added 'none' options to filters for optional fields
This commit is contained in:
43
netbox/utilities/filters.py
Normal file
43
netbox/utilities/filters.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import django_filters
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
|
||||
class NullableModelMultipleChoiceFilter(django_filters.MultipleChoiceFilter):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Convert the queryset to a list of choices prefixed with a "None" option
|
||||
queryset = kwargs.pop('queryset')
|
||||
self.to_field_name = kwargs.pop('to_field_name', 'pk')
|
||||
kwargs['choices'] = [(0, 'None')] + [(getattr(o, self.to_field_name), o) for o in queryset]
|
||||
super(NullableModelMultipleChoiceFilter, self).__init__(*args, **kwargs)
|
||||
|
||||
def filter(self, qs, value):
|
||||
value = value or () # Make sure we have an iterable
|
||||
|
||||
if self.is_noop(qs, value):
|
||||
return qs
|
||||
|
||||
# Even though not a noop, no point filtering if empty
|
||||
if not value:
|
||||
return qs
|
||||
|
||||
q = Q()
|
||||
for v in set(value):
|
||||
# Filtering on NULL
|
||||
if v == str(0):
|
||||
arg = {'{}__isnull'.format(self.name): True}
|
||||
# Filtering on a related field (e.g. slug)
|
||||
elif self.to_field_name != 'pk':
|
||||
arg = {'{}__{}'.format(self.name, self.to_field_name): v}
|
||||
# Filtering on primary key
|
||||
else:
|
||||
arg = {self.name: v}
|
||||
if self.conjoined:
|
||||
qs = self.get_method(qs)(**arg)
|
||||
else:
|
||||
q |= Q(**arg)
|
||||
if self.distinct:
|
||||
return self.get_method(qs)(q).distinct()
|
||||
|
||||
return self.get_method(qs)(q)
|
@@ -43,7 +43,7 @@ def get_filter_choices(model, id_field='pk', select_related=[], count_field=None
|
||||
:param id_field: Field to use as the object identifier
|
||||
:param select_related: Any related tables to include
|
||||
:param count_field: The field to use for a child COUNT() (optional)
|
||||
:param null_option: A (value, label) tuple to include at the beginning of the list serving as "null"
|
||||
:param null_option: A choice to include at the beginning of the list serving as "null"
|
||||
"""
|
||||
queryset = model.objects.all()
|
||||
if select_related:
|
||||
@@ -54,7 +54,7 @@ def get_filter_choices(model, id_field='pk', select_related=[], count_field=None
|
||||
else:
|
||||
choices = [(getattr(obj, id_field), u'{}'.format(obj)) for obj in queryset]
|
||||
if null_option:
|
||||
choices = [null_option] + choices
|
||||
choices = [(0, null_option)] + choices
|
||||
return choices
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user