1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #13585: Introduce 'empty' lookup for numeric value filters

This commit is contained in:
Jeremy Stretch
2023-08-28 15:10:51 -04:00
parent faf89350ac
commit 480f83c42d
3 changed files with 47 additions and 20 deletions

View File

@ -61,13 +61,14 @@ These lookup expressions can be applied by adding a suffix to the desired field'
Numeric based fields (ASN, VLAN ID, etc) support these lookup expressions: Numeric based fields (ASN, VLAN ID, etc) support these lookup expressions:
| Filter | Description | | Filter | Description |
|--------|-------------| |---------|--------------------------|
| `n` | Not equal to | | `n` | Not equal to |
| `lt` | Less than | | `lt` | Less than |
| `lte` | Less than or equal to | | `lte` | Less than or equal to |
| `gt` | Greater than | | `gt` | Greater than |
| `gte` | Greater than or equal to | | `gte` | Greater than or equal to |
| `empty` | Is empty/null (boolean) |
Here is an example of a numeric field lookup expression that will return all VLANs with a VLAN ID greater than 900: Here is an example of a numeric field lookup expression that will return all VLANs with a VLAN ID greater than 900:
@ -79,18 +80,18 @@ GET /api/ipam/vlans/?vid__gt=900
String based (char) fields (Name, Address, etc) support these lookup expressions: String based (char) fields (Name, Address, etc) support these lookup expressions:
| Filter | Description | | Filter | Description |
|--------|-------------| |---------|----------------------------------------|
| `n` | Not equal to | | `n` | Not equal to |
| `ic` | Contains (case-insensitive) | | `ic` | Contains (case-insensitive) |
| `nic` | Does not contain (case-insensitive) | | `nic` | Does not contain (case-insensitive) |
| `isw` | Starts with (case-insensitive) | | `isw` | Starts with (case-insensitive) |
| `nisw` | Does not start with (case-insensitive) | | `nisw` | Does not start with (case-insensitive) |
| `iew` | Ends with (case-insensitive) | | `iew` | Ends with (case-insensitive) |
| `niew` | Does not end with (case-insensitive) | | `niew` | Does not end with (case-insensitive) |
| `ie` | Exact match (case-insensitive) | | `ie` | Exact match (case-insensitive) |
| `nie` | Inverse exact match (case-insensitive) | | `nie` | Inverse exact match (case-insensitive) |
| `empty` | Is empty (boolean) | | `empty` | Is empty/null (boolean) |
Here is an example of a lookup expression on a string field that will return all devices with `switch` in the name: Here is an example of a lookup expression on a string field that will return all devices with `switch` in the name:

View File

@ -20,7 +20,8 @@ FILTER_NUMERIC_BASED_LOOKUP_MAP = dict(
lte='lte', lte='lte',
lt='lt', lt='lt',
gte='gte', gte='gte',
gt='gt' gt='gt',
empty='isnull',
) )
FILTER_NEGATION_LOOKUP_MAP = dict( FILTER_NEGATION_LOOKUP_MAP = dict(

View File

@ -86,6 +86,10 @@ class DummyModel(models.Model):
charfield = models.CharField( charfield = models.CharField(
max_length=10 max_length=10
) )
numberfield = models.IntegerField(
blank=True,
null=True
)
choicefield = models.IntegerField( choicefield = models.IntegerField(
choices=(('A', 1), ('B', 2), ('C', 3)) choices=(('A', 1), ('B', 2), ('C', 3))
) )
@ -108,6 +112,7 @@ class BaseFilterSetTest(TestCase):
""" """
class DummyFilterSet(BaseFilterSet): class DummyFilterSet(BaseFilterSet):
charfield = django_filters.CharFilter() charfield = django_filters.CharFilter()
numberfield = django_filters.NumberFilter()
macaddressfield = MACAddressFilter() macaddressfield = MACAddressFilter()
modelchoicefield = django_filters.ModelChoiceFilter( modelchoicefield = django_filters.ModelChoiceFilter(
field_name='integerfield', # We're pretending this is a ForeignKey field field_name='integerfield', # We're pretending this is a ForeignKey field
@ -132,6 +137,7 @@ class BaseFilterSetTest(TestCase):
model = DummyModel model = DummyModel
fields = ( fields = (
'charfield', 'charfield',
'numberfield',
'choicefield', 'choicefield',
'datefield', 'datefield',
'datetimefield', 'datetimefield',
@ -171,6 +177,25 @@ class BaseFilterSetTest(TestCase):
self.assertEqual(self.filters['charfield__iew'].exclude, False) self.assertEqual(self.filters['charfield__iew'].exclude, False)
self.assertEqual(self.filters['charfield__niew'].lookup_expr, 'iendswith') self.assertEqual(self.filters['charfield__niew'].lookup_expr, 'iendswith')
self.assertEqual(self.filters['charfield__niew'].exclude, True) self.assertEqual(self.filters['charfield__niew'].exclude, True)
self.assertEqual(self.filters['charfield__empty'].lookup_expr, 'empty')
self.assertEqual(self.filters['charfield__empty'].exclude, False)
def test_number_filter(self):
self.assertIsInstance(self.filters['numberfield'], django_filters.NumberFilter)
self.assertEqual(self.filters['numberfield'].lookup_expr, 'exact')
self.assertEqual(self.filters['numberfield'].exclude, False)
self.assertEqual(self.filters['numberfield__n'].lookup_expr, 'exact')
self.assertEqual(self.filters['numberfield__n'].exclude, True)
self.assertEqual(self.filters['numberfield__lt'].lookup_expr, 'lt')
self.assertEqual(self.filters['numberfield__lt'].exclude, False)
self.assertEqual(self.filters['numberfield__lte'].lookup_expr, 'lte')
self.assertEqual(self.filters['numberfield__lte'].exclude, False)
self.assertEqual(self.filters['numberfield__gt'].lookup_expr, 'gt')
self.assertEqual(self.filters['numberfield__gt'].exclude, False)
self.assertEqual(self.filters['numberfield__gte'].lookup_expr, 'gte')
self.assertEqual(self.filters['numberfield__gte'].exclude, False)
self.assertEqual(self.filters['numberfield__empty'].lookup_expr, 'isnull')
self.assertEqual(self.filters['numberfield__empty'].exclude, False)
def test_mac_address_filter(self): def test_mac_address_filter(self):
self.assertIsInstance(self.filters['macaddressfield'], MACAddressFilter) self.assertIsInstance(self.filters['macaddressfield'], MACAddressFilter)