Skip to content

Instantly share code, notes, and snippets.

@jpadilla
Last active March 19, 2020 15:46
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpadilla/809f400c1217ae3e37b6 to your computer and use it in GitHub Desktop.
Save jpadilla/809f400c1217ae3e37b6 to your computer and use it in GitHub Desktop.
Custom MethodFilter for django-filter
from django import forms
from django_filters import filters
filters.LOOKUP_TYPES = [
('', '---------'),
('exact', 'Is equal to'),
('not_exact', 'Is not equal to'),
('lt', 'Lesser than'),
('gt', 'Greater than'),
('gte', 'Greater than or equal to'),
('lte', 'Lesser than or equal to'),
('startswith', 'Starts with'),
('endswith', 'Ends with'),
('contains', 'Contains'),
('not_contains', 'Does not contain'),
]
class MethodFilter(filters.MethodFilter):
def __init__(self, *args, **kwargs):
self.field_class = kwargs.pop('field_class', forms.Field)
kwargs.update({
'lookup_type': None
})
super(MethodFilter, self).__init__(*args, **kwargs)
def filter(self, queryset, value):
lookup_type = value.lookup_type
lookup_value = value.value
if lookup_value in ([], (), {}, None, ''):
return queryset
parent = getattr(self, 'parent', None)
parent_filter_method = getattr(parent, self.parent_action, None)
if parent_filter_method is not None:
return parent_filter_method(queryset, value)
if lookup_type.startswith('not_'):
method = queryset.exclude
else:
method = queryset.filter
if lookup_type.startswith('not_'):
lookup = lookup_type.replace('not_', '')
return method(**{
'{}__{}'.format(self.name, lookup): lookup_value
})
from django import forms
import django_filters
from ..utils.filters import MethodFilter, filter_by_method
from .models import Redemption
STATE_CHOICES = [('', '---------')] + \
Redemption._meta.get_field_by_name('state')[0].choices
class RedemptionFilter(django_filters.FilterSet):
user__email = MethodFilter(
field_class=forms.CharField
)
date_created = MethodFilter(
field_class=forms.DateField
)
amount = MethodFilter(
field_class=forms.DecimalField,
action='filter_amount'
)
state = MethodFilter(
field_class=forms.ChoiceField,
choices=STATE_CHOICES
)
class Meta:
model = Redemption
fields = [
'user__email', 'amount', 'date_created', 'state'
]
def filter_amount(self, queryset, value):
return filter_by_method(queryset, value, 'amount')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment