【问题标题】:Custom FilterSet doesn't filter by two fields at the same time自定义过滤器集不会同时按两个字段过滤
【发布时间】:2019-06-19 22:10:31
【问题描述】:

我编写了自定义 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')))

【问题讨论】:

    标签: django django-orm django-filters


    【解决方案1】:

    您的问题在这一行:

                   return self.queryset.filter(Q(status=Event.STARTED) | (Q(status=Event.NOT_STARTED, start_at__range=interval)))
    

    您正在使用来自 FilterSet 类本身的查询集。此查询集没有应用任何以前的过滤器,因此通过使用它,您将取消另一个过滤器。只需从此行中删除 self. 以使用作为参数传递给此函数的查询集,一切都会正常工作。

    【讨论】:

      猜你喜欢
      • 2011-04-28
      • 2014-04-30
      • 2018-02-13
      • 2017-03-09
      • 2018-09-08
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多