Last active
January 4, 2019 10:20
-
-
Save zorky/47e808146b6dc00f1e09335b03418344 to your computer and use it in GitHub Desktop.
Generic filter with operators (gt, lt, eq, ne) on model's field
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import django_filters | |
import datetime | |
from django.db.models import Q | |
class FilterOperatorBase(django_filters.FilterSet): | |
""" | |
base filter for field_operator | |
field_operator is formatted as : field||type||operator||value | |
separator is || | |
- field : model's field | |
- type : date, number, string, list | |
- operator : gt | lt | eq | ne or range for date (value must be in format : datebegin_dateend as YYYY-MM-DD_YYYY-MM-DD) | |
- value : value to test | |
""" | |
field_operator = django_filters.CharFilter(method="get_field_operator") | |
def get_field_operator(self, queryset, name, value): | |
""" | |
Management of fields operator "field_operator", multi values | |
ie : field_operator=val1&field_operator=val2&field_operator=valn where val has format field||type||operator||value | |
""" | |
qs = queryset | |
field_operator_list = self.request.GET.getlist('field_operator') | |
for field in field_operator_list: | |
field, type, operator, valuefield = field.split('||') | |
if field and type and operator and valuefield: | |
if type == 'date': | |
if operator == 'range': | |
# value = YYYY-MM-DD_YYYY-MM-DD : date_begin_date_end | |
date_begin, date_end = value.split('_') | |
values = {'date_begin': date_begin, 'date_end': date_end} | |
else: | |
year, month, day = valuefield.split('-') | |
date = datetime.date(int(year), int(month), int(day)) | |
values = {'date': date, 'day': day, 'month': month, 'year': year} | |
q = self.__get_date_filter_operator(field=field, operator=operator, **values) | |
qs = qs.filter(q) | |
if type == 'number': | |
q = self.__get_number_filter_operator(field=field, operator=operator, value=valuefield) | |
qs = qs.filter(q) | |
if type == 'string': | |
q = self.__get_string_filter_operator(field=field, operator=operator, value=valuefield) | |
qs = qs.filter(q) | |
if type == 'list': | |
ids = list(valuefield) | |
filter = { | |
'{}__in'.format(field): ids | |
} | |
if operator == 'eq': | |
qs = qs.filter(**filter) | |
if operator == 'ne': | |
qs = qs.exclude(**filter) | |
return qs | |
def __get_string_filter_operator(self, field, operator, value, insensibleCasse = True): | |
""" | |
Creating Q for string (eq or ne only operators) | |
""" | |
q = None | |
filter = { | |
'{}__{}'.format(field, 'iexact' if insensibleCasse else 'exact'): value | |
} | |
if operator == 'eq': | |
q = Q(**filter) | |
if operator == 'ne': | |
q = ~Q(**filter) | |
return q | |
def __get_number_filter_operator(self, field, operator, value): | |
""" | |
Created Q for numbers (lte or gte or eq or ne) | |
""" | |
filter = {} | |
q = None | |
if operator == 'gte' or operator == 'lte' or operator == 'eq': | |
if operator == 'gte' or operator == 'lte': | |
filter = { | |
'{}__{}'.format(field, operator): value | |
} | |
if operator == 'eq': | |
filter = { | |
'{}'.format(field): value | |
} | |
q = Q(**filter) | |
if operator == 'ne': | |
filter = { | |
'{}'.format(field): value | |
} | |
q = ~Q(**filter) | |
return q | |
def __get_date_filter_operator(self, field, operator, **values): | |
""" | |
Created Q for date (lt or gt or eq or ne operators) | |
""" | |
filter = {} | |
q = None | |
if operator == 'gt' or operator == 'lt' or operator == 'eq': | |
if operator == 'gt' or operator == 'lt': | |
filter = { | |
'{}__{}'.format(field, operator): values['date'] | |
} | |
if operator == 'eq': | |
filter = { | |
'{}__day'.format(field): values['day'], | |
'{}__month'.format(field): values['month'], | |
'{}__year'.format(field): values['year'] | |
} | |
q = Q(**filter) | |
if operator == 'ne': | |
filter = { | |
'{}__day'.format(field): values['day'], | |
'{}__month'.format(field): values['month'], | |
'{}__year'.format(field): values['year'] | |
} | |
q = ~Q(**filter) | |
if operator == 'range': | |
filter = { | |
'{}__range'=[values['date_begin'], values['date_end']] | |
} | |
q = Q(**filter) | |
return q |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment