#python #django #django-filter
#питон #джанго #django-фильтр
Вопрос:
У меня есть модель, которая имеет create_date
, update_date
, release_date
DateTimeField.
Я хотел бы иметь фильтр для их DateTimeField
DateFilter
фильтрации . Вот один из способов, которым я могу это сделать:
class ProductFilter(django_filters.FilterSet):
create_date = DateFilter(field_name='create_date', lookup_expr='date')
create_date__gt = DateFilter(field_name='create_date', lookup_expr='date__gt')
create_date__lt = DateFilter(field_name='create_date', lookup_expr='date__lt')
create_date__gte = DateFilter(field_name='create_date', lookup_expr='date__gte')
create_date__lte = DateFilter(field_name='create_date', lookup_expr='date__lte')
update_date = DateFilter(field_name='update_date', lookup_expr='date')
update_date__gt = DateFilter(field_name='update_date', lookup_expr='date__gt')
update_date__lt = DateFilter(field_name='update_date', lookup_expr='date__lt')
update_date__gte = DateFilter(field_name='update_date', lookup_expr='date__gte')
update_date__lte = DateFilter(field_name='update_date', lookup_expr='date__lte')
release_date = DateFilter(field_name='release_date', lookup_expr='date')
release_date__gt = DateFilter(field_name='release_date', lookup_expr='date__gt')
release_date__lt = DateFilter(field_name='release_date', lookup_expr='date__lt')
release_date__gte = DateFilter(field_name='release_date', lookup_expr='date__gte')
release_date__lte = DateFilter(field_name='release_date', lookup_expr='date__lte')
Вы можете увидеть, что все становится повторяющимся. Есть ли какой-нибудь способ инкапсулировать логику?
P.S. Я знаю, что могу использовать Meta.fields
, как:
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = {
'create_date': ['date', 'date__gt', 'date__lt', 'date__gte', 'date__lte'],
'update_date': ['date', 'date__gt', 'date__lt', 'date__gte', 'date__lte'],
'release_date': ['date', 'date__gt', 'date__lt', 'date__gte', 'date__lte'],
}
но имя фильтра станет create_date__date
вместо create_date
.
Комментарии:
1. Вы можете использовать только
lte
иgte
для меньших и больших значений. т.е.['exact', 'let's, 'gte']
exact
поиск проверит точную дату.
Ответ №1:
Вы можете переопределить __init__(...)
метод FilterSet
класса как,
field_names = ["create_date", "update_date", "release_date"]
lookup_expr = ["gt", "lt", "gte", "lte"]
filter_dict = {}
for field_name in field_names:
filter_dict[field_name] = DateFilter(lookup_expr="date")
for expr in lookup_expr:
filter_dict[f"{field_name}_{expr}"] = DateFilter(
field_name=field_name,
lookup_expr=f"date__{expr}"
)
class FooFilter(filters.FilterSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.filters.update(filter_dict)
Ответ №2:
Вы можете определить метод класса, который задает атрибуты. Но вы должны вызвать его где-нибудь, например, сразу после его определения.
class ProductFilter(django_filters.FilterSet):
@classmethod
def init_attr(klass):
field_names = ["create_date", "update_date", "release_date"]
lookup_expr = ["", "__gt", "__lt", "__gte", "__lte"]
for field_name in field_names:
for expr in lookup_expr:
setattr(klass, field_name expr, DateFilter(field_name=field_name, lookup_expr='date' expr))
PoductFilter.init_attr()