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

Posted

技术标签:

【中文标题】当过滤字符串为空时,如何停止 Graphql + Django-Filters 返回所有对象?【英文标题】:How to stop Graphql + Django-Filters to return All Objects when Filter String is Empty? 【发布时间】:2020-05-17 11:52:57 【问题描述】:

使用:

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

我有一个简单的 Birds Django 模型,其中包含 namehabitat 等字段,并在这些字段上应用了不同的过滤器icontainsiexact 等字段。我的目标是在我的前端 (Vue) 中应用一个简单的搜索字段。到目前为止它可以工作,但是只要这个过滤器值是空的或有空格(参见示例 3),Graphql 就会返回所有对象。

我的第一种方法是在前端,并在我的输入值上使用某种逻辑,例如当 String 为 Empty/blank 时发送 isnull=true 。但后来我认为 Django 应该首先处理这个问题。 我想这个问题与我的 filters (参见 Django 或换句话说我必须在这些过滤器上应用某种逻辑有关吗?

在我尝试自定义一些filterset_class 的那一刻,但感觉这可能太多了,也许我错过了什么?所以我在这里问是否有人有一些提示,因此我的问题是:

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...>

不适合我!

姜戈

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) 

【问题讨论】:

我同意这种行为不是预期的,但解决方法很简单,不允许在输入为空时进行搜索。 【参考方案1】:

这是我在 GraphiQL 和我的前端 VUE 中工作的解决方案。 我为每个过滤器添加了Birds2Query 的逻辑def resolve_all_birds2(用于测试目的,并非针对所有过滤器)。 除此之外,我还添加了一个ExtendedConnection 用于计数。

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

更新:此解决方案适用于 python 端。但是apollo client 还提供了Apollo manager - 也称为Dollar Apollo - 您还可以使用this.$apollo.queries.tags.skip 属性作为启动和停止查询的静态或动态解决方案。

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"
          
        
      ]
    
  

【讨论】:

以上是关于当过滤字符串为空时,如何停止 Graphql + Django-Filters 返回所有对象?的主要内容,如果未能解决你的问题,请参考以下文章

仅当变量不为空时,如何应用 Hasura `where` 过滤器?

仅当搜索栏文本不为空时,如何运行过滤器功能?

当过滤器为空时,它返回空数组

当多个输入可以为空时,在 Django 中使用 Q 进行过滤

x-editable,当字符串为空时如何显示特定值?

我创建了一个添加两个数字的应用程序但是当编辑文本为空时按下按钮的应用程序一直停止