如何编写将使用`django-filters`在整数字段上使用范围过滤器的GraphQL查询? 参考

问题描述

我在GraphQL API中使用graphene-pythondjango-filtersrelay。假设我有一个类型为FrameType的类型,该类型具有一个整数字段time_offset,并且我希望能够在其上使用 range -仅询问具有{ {1}}在给定范围内。我根据graphene-python docs自定义time_offset准备了schema.py

FilterSet

但是,我现在不知道如何查询import django_filters from graphene import ObjectType,relay from graphene_django import DjangoObjectType,filter from my_app.blabla import models class FrameFilter(django_filters.FilterSet): time_offset = django_filters.RangeFilter() class Meta: model = models.Frame fields = ("time_offset",) class FrameType(DjangoObjectType): class Meta: model = models.Frame filterset_class = FrameFilter interfaces = (relay.Node,) class Query(ObjectType): frames = filter.DjangoFilterConnectionField(FrameType) class Meta: abstract = True 字段。我没有在线找到timeOffset字段的示例。这是我尝试过的查询

django_filters.RangeFilter

...还有这些替代方案:

query Frame {
  frames(first: 20,timeOffset: "{\"gt\":\"4350\",\"lt\":\"5000\"}") {
    edges {
      node {
        timeOffset
    }
  }
}

这些查询不会引发任何错误,但是也不会过滤(返回所有结果)。我迷路了,我不确定是否仍然没有找到正确的语法,或者我的后端代码中有一些错误。我应该如何在字段上使用和查询timeOffset: "{\"gt\":4350,\"lt\":5000}" timeOffset: "{\"start\":\"4350\",\"end\":\"5000\"}" timeOffset: "{\"min\":\"4350\",\"max\": \"4500\"}" timeOffset: "[\"4350\",\"5000\"]" timeOffset: "[4350,5000]" timeOffset: "[4350]" timeOffset: "4350,5000"

解决方法

遗憾的是,这是不可能的。但是,有一种解决方法

将过滤器类别调整为

def custom_range_filter_method(queryset,field_name,value):
    if value:
        queryset = queryset.filter(**{f'{field_name}__range': value.split(',')})
    return queryset


class FrameFilter(django_filters.FilterSet):
    time_offset = filters.Filter(method=custom_range_filter_method)

    class Meta:
        model = models.Frame
        fields = ("time_offset",)

现在使用

查询架构
query Frame {
  frames(first: 20,timeOffset: "4350,5000") {
    edges {
      node {
        timeOffset
    }
  }
}

参考

,

您可以在Django的查询集级别处理 range 选项,而不会干扰现有的中继查询。

就您而言,

  1. start_time_offsetend_time_offset参数传递给DjangoConnectionField
  2. 覆盖resolve_frames
  3. 如果用户提供了start_time_offsetend_time_offset,则对Django查询集进行过滤,否则返回objects.all()
class Query(ObjectType):
    frames = filter.DjangoFilterConnectionField(FrameType,start_time_offset=graphene.Int(),end_time_offset=graphene.Int())

    def resolve_scans(self,info,start_time_offset=None,end_time_offset=None,**kwargs):
        if start_time_offset and end_time_offset:
            return Frame.objects.filter(time_offset__range=(start_time_offset,end_time_offset))
        elif start_time_offset:
            return Frame.objects.filter(time_offset__gte=start_time_offset)
        elif end_time_offset:
            return Frame.objects.filter(time_offset__lte=end_time_offset)
        return Frame.objects.all()

现在,您可以使用中继提供的常规过滤器对其进行查询:

query Frame {
  frames(last: 5,startTimeOffset: 4350,endTimeOffset:5000) {
    edges {
      node {
        timeOffset
    }
  }
}
,

它有点旧,但因为它可能对其他人有帮助,您可以检查这个 thread,它使用 django filterset for DateRangeFiled,我认为您可以使用 filterset RangeFilter 对整数使用类似的方法。另请查看 this 以了解有关石墨烯过滤器集的更多信息。