在Django Graphene Relay中启用基于PK的过滤,同时保留全局ID

问题描述 投票:3回答:1

Problem

我在GraphQL Server上使用django-graphene和Relay。该实现在Global ID requirement类中强加了一个graphene.relay.Node,它覆盖并隐藏了Django的ID字段。

结果,我可以像这样查询:

{
    allBatches(id:"QmF0Y2hOb2RlOjE=") {
    edges {
      node {
        id
        pk
      }
    }
  }
}

得到这个回应:

{
  "data": {
    "allBatches": {
      "edges": [
        {
          "node": {
            "id": "QmF0Y2hOb2RlOjE=",
            "pk": 1
          }
        }
      ]
    }
  }
}

但是,我失去的是能够按对象本身的原始ID(或PK)字段进行过滤:

{
    allBatches(id:1) {
    edges {
      node {
        id
        pk
      }
    }
  }
}

实际上,我根本无法通过ID过滤对象。我可以想到两个可能的解决办法:1。防止django-graphene-relay劫持和遮蔽id字段,也许强迫它使用不同的字段名称,如gid 2.找到一种方法将pk包括在内可作为属性和过滤器使用的特殊字段

Solution 1

我在1上没有取得任何进展,因为看起来好像django-graphene(也许是接力标准)强加了这个领域被称为id的限制。我看到id已被用作多个地方的魔术字符串,并且似乎没有更改字段名称的标准方法。

Solution 2

在2,我可以让这个属性与这样的Mixin一起工作:

class PKMixin(object):
    pk = graphene.Field(type=graphene.Int, source='pk')

但是,我无法通过django-filter进行过滤工作,因为FilterSet没有声明字段pk并打破以下错误

'Meta.fields'包含未在此FilterSet上定义的字段:pk

更新2

我尝试了以下方法:

class PKFilteringNode(Node):

    @classmethod
    def get_node_from_global_id(cls, info, global_id, only_type=None):
        # So long as only_type is set; if we detect that the global_id is a pk and not a global ID;
        # then coerce it to be a proper global ID before fetching
        if only_type:
            try:
                int(global_id)
                global_id = cls.to_global_id(only_type._meta.name, global_id)
                return super(PKFilteringNode, cls).get_node_from_global_id(info, global_id, only_type)
            except ValueError:
                pass
        return super(PKFilteringNode, cls).get_node_from_global_id(info, global_id, only_type)

现在我可以使用GraphQL来执行此操作:

{
  batchA: batch(id: "QmF0Y2hOb2RlOjE=") {
    id
    name
  }
  batchB: batch(id: 1) {
    id
    name
  }
}
{
  "data": {
    "batchA": {
      "id": "QmF0Y2hOb2RlOjE=",
      "name": "Default Batch"
    },
    "batchB": {
      "id": "QmF0Y2hOb2RlOjE=",
      "name": "Default Batch"
    }
  }
}

但我有一种相当强烈的恐惧,这可能会破坏下游的某些东西,或许在缓存水平?此外,由于过滤依赖于DjangoFilterConnectionField,因此不允许按ID过滤

Request

我现在卡住了。我有几个问题:

  1. 这是一个不寻常的要求开始?当我希望保留通过pk过滤的能力时,我是否提出了错误的问题
  2. 是否有标准模式来解决这个问题?

关于Github的相关问题

https://github.com/graphql-python/graphene-django/issues/349

版本

  • 石墨烯的Django == 2.1.0
  • Django的== 1.9.12
  • Django的过滤器== 1.0.1
  • 蟒蛇== 2.7.13
python django graphql relay graphene-python
1个回答
0
投票

您是否尝试过解决方案2,但使用id作为源代码?

class PKMixin(object):
    pk = graphene.Field(type=graphene.Int, source='id')

此外,如果您只想获取单个记录,则无论如何都不应通过连接字段。您应该在架构上定义类似batchByPk字段的内容。

最后需要注意的是,目前graphene-django的DjangoFilterConnectionField并没有以有效的方式实现,所以你甚至可能都不想使用它。

© www.soinside.com 2019 - 2024. All rights reserved.