温馨提示:本文翻译自stackoverflow.com,查看原文请点击:其他 - How to stop Graphql + Django-Filters to return All Objects when Filter String is Empty?
django graphql graphene-python django-filters vue-apollo

其他 - 当过滤器字符串为空时,如何停止Graphql + Django-Filters返回所有对象?

发布于 2020-04-07 23:38:48

使用:

  • Django 3.x [Django-Filters 2.2.0,graphene-django 2.8.0,graphql-relay 2.0.1]
  • Vue 2.x [Vue-Apollo]

我有一个简单的BirdsDjango模型,其字段为namehabitat并在icontains上对这些字段应用了不同的过滤器iexact我的目标是在Frontend(Vue)中应用一个简单的搜索字段。到目前为止,它仍然有效,但是只要此Filter Value为空或有空白(请参见示例3),Graphql就会返回所有Object。

我的第一种方法是在FrontEnd上,并对输入值使用某种逻辑,例如String为Empty / blank send时isnull=true但是后来我认为Django应该首先处理这个问题。我猜这个问题与我的问题有关(请参阅Django <relay_schema.py),换句话说,我是否必须对这些过滤器应用某种逻辑?filters

目前,我尝试自定义一些内容,filterset_class但感觉可能会太多,也许我错过了一些内容?所以我在这里问是否有人暗示,所以我的问题是:

当过滤器字符串为空时,如何停止Graphql + Django-Filters返回所有对象?

GraphiQL IDE

例子1


query {birdsNodeFilter (name_Iexact: "finch") {
  edges {
    node {
      id
      name
    }
     }
    }
}

退货

{
  "data": {
    "birdsNodeFilter": {
      "edges": [
        {
          "node": {
            "id": "QmlyZHNOb2RlOjE=",
            "name": "Finch",
            "habitat": "Europe"
          }
        }
      ]
    }
  }
}

对我来说没问题!

例子2


query {birdsNodeFilter (name_Iexact: "Unicorns") {
  edges {
    node {
      id
      name
      habitat
    }
     }
    }
}

退货

{
  "data": {
    "birdsNodeFilter": {
      "edges": []
    }
  }
}

那里没有独角兽-很好

例子3


query {birdsNodeFilter (name_Iexact: "") {
  edges {
    node {
      id
      name
    }
     }
    }
}

返回

{
  "data": {
    "birdsNodeFilter": {
      "edges": [
        {
          "node": {
            "id": "QmlyZHNOb2RlOjE=",
            "name": "Finch",
            "habitat": "Europe"
          }
        },
        {
          "node": {
            "id": "QmlyZHNOb2RlOjI=",
            "name": "Bald Eagle",
            "habitat": "USA"
          }
        },

<...And so on...>

对我不好!

Django的

relay_schema.py


class BirdsNode(DjangoObjectType):
    class Meta:
        model = Birds
        filter_fields = {
            'id': ['iexact'],
            'name': ['iexact', 'icontains', 'istartswith', 'isnull'],
            'habitat': ['iexact', 'icontains', 'istartswith'],
        }
        interfaces = (relay.Node, )


class BirdQuery(graphene.ObjectType):
    birdConNode = relay.Node.Field(BirdsNode)
    birdsNodeFilter = DjangoFilterConnectionField(BirdsNode) 

查看更多

提问者
black_hole_sun
被浏览
63
black_hole_sun 2020-02-15 03:33

这是我在GraphiQL和Frontend VUE中使用的解决方案。我添加了一个逻辑到Birds2Querydef resolve_all_birds2每个过滤器(对所有过滤器不是测试目的)。除此之外,我还增加了一个ExtendedConnection计数。

注意:我从以前的问题中更改了类名。

relay_schema.py

class ExtendedConnection(Connection):
    class Meta:
        abstract = True

    total_count = Int()
    edge_count = Int()
    name_check = ""

    def resolve_total_count(root, info, **kwargs):
        return root.length
    def resolve_edge_count(root, info, **kwargs):
        return len(root.edges)

class Birds2Node(DjangoObjectType):
    class Meta:

        model = Birds
        filter_fields =  {
            'id':  ['exact', 'icontains'],
            'name': ['exact', 'icontains', 'istartswith', 'iendswith'],
        }

        interfaces = (relay.Node, )
        connection_class = ExtendedConnection

class Birds2Query(ObjectType):
    birds2 = relay.Node.Field(Birds2Node)
    all_birds2 = DjangoFilterConnectionField(Birds2Node)


    def resolve_all_birds2(self, info, **kwargs):
        # Filtering for Empty/ Blank Values in Filter.Key.Value before returning queryset
         if 'name__icontains' in kwargs:
            nameIcon = kwargs['name__icontains']
            nameIconBool = bool(nameIcon.strip()) # if blanks turns False           
            if nameIconBool == False: # has blanks         
                return Birds.objects.filter(name=None)
            pass


        if 'name__istartswith' in kwargs:           
            nameIsta = kwargs['name__istartswith']
            nameIstaBool = bool(nameIsta.strip()) # if blanks turns False          
            if nameIstaBool == False: # has blanks         
                return Birds.objects.filter(name=None)
            pass
         return

GraphiQL 大段引用

例子1

query {allBirds2 (name_Icontains:""){
  totalCount
    edgeCount
    edges {
      node {
        id
        name
        habitat
      }  
    }
  }
}

过滤器为空时停止返回所有对象。

{
  "data": {
    "allBirds2": {
      "totalCount": 0,
      "edgeCount": 0,
      "edges": []
    }
  }
}

示例2,带空格和一个字母

query {allBirds2 (name_Icontains:" f  "){
  totalCount
    edgeCount
    edges {
      node {
        id
        name
        habitat
      }  
    }
  }
}

返回-正是我想要的

{
  "data": {
    "allBirds2": {
      "totalCount": 1,
      "edgeCount": 1,
      "edges": [
        {
          "node": {
            "id": "QmlyZHMyTm9kZTox",
            "name": "Finch",
            "habitat": "Europe"
          }
        }
      ]
    }
  }
}