Skip to content

Commit

Permalink
Merge pull request #179 from Teknologforeningen/feature/null-char-filter
Browse files Browse the repository at this point in the history
Added an extended CharFilter that can filter null/~null if given cert…
  • Loading branch information
filiptypjeu authored Aug 30, 2023
2 parents 0ec1de2 + 8a7aac7 commit 6fd6c24
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
30 changes: 24 additions & 6 deletions teknologr/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,30 @@

class BooleanFilter(django_filters.BooleanFilter):
'''
The defualt null label is for some reason 'unknown', but I want it to be ''
The default null label is for some reason 'unknown', but I want it to be ''
'''
def __init__(self, *args, **kwargs):
kwargs['widget'] = django_filters.widgets.BooleanWidget
super().__init__(*args, **kwargs)

class CharFilterWithKeywords(django_filters.CharFilter):
'''
Take a CharFilter. You can filter on a specific phrase or leave it empty, but what if you want to filter null/empty values? This filter applies predetermined null/~null filters if the value is a certain keyword:
- '-' => isnull=True
- '*' => isnull=False
Not suitable for fields where the keywords are possible values, and does not apply if the 'method' argument is given in the constructor.
'''

def filter(self, qs, value):
q = Q(**{f'{self.field_name}__isnull': True}) | Q(**{f'{self.field_name}__exact': ''})
if value == '-':
return qs.filter(q)
if value == '*':
return qs.exclude(q)
return super().filter(qs, value)


class BaseFilter(django_filters.rest_framework.FilterSet):
'''
Base filter class that takes care of normal users from using staff-only filters.
Expand Down Expand Up @@ -92,11 +110,11 @@ class MemberFilter(BaseFilter):
method='filter_address',
label='Adressen innehåller',
)
email = django_filters.CharFilter(
email = CharFilterWithKeywords(
lookup_expr='icontains',
label='E-postadressen innehåller',
)
degree_programme = django_filters.CharFilter(
degree_programme = CharFilterWithKeywords(
lookup_expr='icontains',
label='Studieprogrammet innehåller',
)
Expand All @@ -116,7 +134,7 @@ class MemberFilter(BaseFilter):
birth_date = django_filters.DateFromToRangeFilter(
label='Född mellan',
)
student_id = django_filters.CharFilter(
student_id = CharFilterWithKeywords(
label='Studienummer',
)
dead = BooleanFilter(
Expand All @@ -135,10 +153,10 @@ class MemberFilter(BaseFilter):
lookup_expr='icontains',
label='Kommentaren innehåller',
)
username = django_filters.CharFilter(
username = CharFilterWithKeywords(
label='Användarnamn',
)
bill_code = django_filters.CharFilter(
bill_code = CharFilterWithKeywords(
label='BILL-konto',
)

Expand Down
40 changes: 40 additions & 0 deletions teknologr/api/tests_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,46 @@ def setUp(self):
dead=False,
)

class MemberFilterUsernameNullTest(BaseAPITest, TestCases):
def setUp(self):
super().setUp()

self.query = 'username=-'
self.n_normal = 3 # Filter does not work for normal users
self.n_staff = 2

# Should only be found by staff
Member.objects.create(
given_names='Test',
surname='von Test',
username='',
)
Member.objects.create(
given_names='Test',
surname='von Test',
username=None,
)

class MemberFilterUsernameAnyTest(BaseAPITest, TestCases):
def setUp(self):
super().setUp()

self.query = 'username=*'
self.n_normal = 3 # Filter does not work for normal users
self.n_staff = 1

# Should not be found by staff
Member.objects.create(
given_names='Test',
surname='von Test',
username='',
)
Member.objects.create(
given_names='Test',
surname='von Test',
username=None,
)


class MemberFilterBillCodeTest(BaseAPITest, TestCases):
def setUp(self):
Expand Down

0 comments on commit 6fd6c24

Please sign in to comment.