自定义FilterSet不会同时过滤两个字段
Custom FilterSet doesn't filter by two fields at the same time
我编写了自定义 FilterSet 以按两个字段过滤查询集,但当它同时过滤两个字段时无法正常工作。
我的过滤器集:
class EventFilter(filters.FilterSet):
values = None
default = None
category = filters.ModelMultipleChoiceFilter(
queryset=EventCategory.objects.all(),
)
interval = filters.CharFilter(
method='filter_interval'
)
class Meta:
model = Event
fields = ('category', 'interval')
def filter_interval(self, queryset, name, value):
if self.request.query_params.get('current_time'):
try:
interval = getattr(self, f'get_{value}_interval')()
interval = list(map(lambda date: self.to_utc(date), interval))
return self.queryset.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED, start_at__range=interval)))
except Exception as e:
pass
return queryset
API 视图:
class ListEventsAPIView(generics.ListAPIView):
serializer_class = ListEventsSerializer
filter_class = EventFilter
search_fields = 'title',
filter_backends = filters.SearchFilter, DjangoFilterBackend
def get_queryset(self):
return Event.objects.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED) & Q(start_at__gte=date)))
这是 SQL 当我尝试仅按类别过滤时生成的:
SELECT "*" FROM "events" WHERE (("events"."status" = 'started'
OR ("events"."status" = 'not_started'
AND "events"."start_at" >= '2019-06-19T13:24:26.444183+00:00'::timestamptz))
AND "events"."category_id" = 'JNPIZF54n5q')
当我对两者进行过滤时:
SELECT "*" FROM "events" WHERE (("events"."status" = 'started'
OR ("events"."status" = 'not_started' AND "events"."start_at" >= '2019-06-19T13:24:26.444183+00:00'::timestamptz))
AND ("events"."status" = 'started' OR ("events"."start_at" BETWEEN '2019-06-19T07:16:48.549000+00:00'::timestamptz AND '2019-06-30T20:59:59.000059+00:00'::timestamptz AND "events"."status" = 'not_started')))
您的问题在这一行:
return self.queryset.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED, start_at__range=interval)))
您正在使用 FilterSet class 本身的查询集。此查询集没有应用任何以前的过滤器,因此通过使用它您将取消另一个过滤器。只需从此行中删除 self.
以使用传递给此函数的查询集作为参数,一切都会正常工作。
我编写了自定义 FilterSet 以按两个字段过滤查询集,但当它同时过滤两个字段时无法正常工作。
我的过滤器集:
class EventFilter(filters.FilterSet):
values = None
default = None
category = filters.ModelMultipleChoiceFilter(
queryset=EventCategory.objects.all(),
)
interval = filters.CharFilter(
method='filter_interval'
)
class Meta:
model = Event
fields = ('category', 'interval')
def filter_interval(self, queryset, name, value):
if self.request.query_params.get('current_time'):
try:
interval = getattr(self, f'get_{value}_interval')()
interval = list(map(lambda date: self.to_utc(date), interval))
return self.queryset.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED, start_at__range=interval)))
except Exception as e:
pass
return queryset
API 视图:
class ListEventsAPIView(generics.ListAPIView):
serializer_class = ListEventsSerializer
filter_class = EventFilter
search_fields = 'title',
filter_backends = filters.SearchFilter, DjangoFilterBackend
def get_queryset(self):
return Event.objects.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED) & Q(start_at__gte=date)))
这是 SQL 当我尝试仅按类别过滤时生成的:
SELECT "*" FROM "events" WHERE (("events"."status" = 'started'
OR ("events"."status" = 'not_started'
AND "events"."start_at" >= '2019-06-19T13:24:26.444183+00:00'::timestamptz))
AND "events"."category_id" = 'JNPIZF54n5q')
当我对两者进行过滤时:
SELECT "*" FROM "events" WHERE (("events"."status" = 'started'
OR ("events"."status" = 'not_started' AND "events"."start_at" >= '2019-06-19T13:24:26.444183+00:00'::timestamptz))
AND ("events"."status" = 'started' OR ("events"."start_at" BETWEEN '2019-06-19T07:16:48.549000+00:00'::timestamptz AND '2019-06-30T20:59:59.000059+00:00'::timestamptz AND "events"."status" = 'not_started')))
您的问题在这一行:
return self.queryset.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED, start_at__range=interval)))
您正在使用 FilterSet class 本身的查询集。此查询集没有应用任何以前的过滤器,因此通过使用它您将取消另一个过滤器。只需从此行中删除 self.
以使用传递给此函数的查询集作为参数,一切都会正常工作。