Один и тот же FilterSet действует по-разному в двух местах
Я использую один и тот же filterset_class
для фильтрации результатов в FE и для генерации отчета в excel. В FE все работает хорошо, результаты фильтруются правильно, но для генерации отчета в excel фильтр period
не применяется. При отладке я вижу, что фильтры периода доступны в filter_args
(см. комментарий в нижнем блоке кода), но не применяются: count(logs)
должен быть 1, но он равен 17.
Так, что-то происходит между объявлением filter_args
и logs
в get_serialized_data
, но не удалось выяснить что. Есть идеи?
views.py
class LogFilterSet(FilterSet):
model_names = [t.target_class._meta.model_name for t in ALLOWED_SELECTION_TARGET_MODELS]
employee = NumberFilter(field_name="owner__id")
company = NumberFilter(field_name="owner_company__id")
period = CustomIsoDateTimeRangeFilter(field_name="start")
class LogViewSet(viewsets.ModelViewSet):
queryset = Log.objects.prefetch_related("selections").reverse().with_add_data()
serializer_class = LogSerializer
filter_backends = (DjangoFilterBackend,)
filterset_class = LogFilterSet
search_fields = None
def get_queryset(self):
queryset = super().get_queryset()
if self.action in ["list", "detail"]:
return queryset.for_role(self.request.role)
return queryset.writable_for_role(self.request.role)
CustomIsoDateTimeRangeFilter
in utils.py
class CustomMultiWidget(MultiWidget):
def __init__(self, attrs=None):
widgets = ()
super().__init__(widgets, attrs)
def value_from_datadict(self, data, files, name):
return data.getlist(name) if isinstance(data, QueryDict) else []
class CustomIsoDateTimeRangeField(IsoDateTimeRangeField):
widget = WaybillerMultiWidget
class CustomIsoDateTimeRangeFilter(RangeFilter):
field_class = IsoDateTimeRangeField
Отфильтрованный набор запросов для генерации в excel:
def get_serialized_data(self):
logs = (
Log.objects.prefetch_related("selections")
.for_role(self.request.role)
.with_add_data()
.reverse()
)
if filter_args := self.request.kwargs.get("filters"): # {'period': ['2022-09-06T21:00:00.000Z', '2022-09-07T20:59:59.000Z'], 'employee': 36}
_filter = LogFilterSet(data=filter_args, queryset=logs)
if not _filter.is_valid():
raise ValueError("Invalid filters!")
logs = _filter.qs # here count(logs) should be 1, but is 17. Only 'employee' filter is applied.
serializer = LogSerializer(
logs,
many=True,
)
return serializer.data