2

到目前为止,我能够在不需要DjangoObjectType. 我尽量避免它,因为我不打算离我的 Django 模型类太近。但是,我在使用 Graphene 实现 Relay 时遇到了问题:

class HouseholdNode(graphene.ObjectType):
  class Meta:
    interfaces = (graphene.relay.Node,)

  name = graphene.String()

  @classmethod
  def get_node(cls, info, id):
    return Household.objects.get(pk=id)

这失败并出现以下错误:

抽象类型节点必须在运行时为字段 Query.node 解析为对象类型,值为“Test”,收到“None”。

“测试”直接来自Household__str__函数。

下次尝试:

  @classmethod
  def get_node(cls, info, id):
    return cls(Household.objects.get(pk=id))

clsHouseholdNode。然而,这会产生错误的结果:

"node": {
  "id": "SG91c2Vob2xkOlRlc3Q=",
  "name": null
}

ID实际上是“测试”。

有效的解决方案:

  @classmethod
  def get_node(cls, info, id):
    household = Household.objects.get(pk=id)
    return cls(name=household.name)

然而,我非常怀疑这就是 Graphene 能为我做的所有事情。我真的必须将真实的数据对象包装到 中HouseholdNode吗?我已经有解决功能,不能简单地使用它们吗?

这些边缘上的文档非常缺乏,请赐教。

4

1 回答 1

0

抽象类型(如graphene.relay.node.Node)由executor使用graphql.execution.executor.complete_abstract_value.

Node实际上,作为接口的 ObjectTypes从石墨烯传递到 graphql 层,每个都包装为GrapheneInterfaceType. 这些resolve_type对象中的每一个(最终提供了错误的来源)调用graphql.execution.executor.get_default_resolve_type_fn.

该函数缩小了可能返回的类型(possible_types),然后遍历这些类型,检查is_type_of属性是否可调用以及它是否返回 True。重要的是要注意possible_types是用户定义的子类Node,继承graphene.types.objecttype.ObjectTypeis_type_of = None。因此,你得到了GraphQLError因为没有类型被解决。

解决方案是在您的对象类型上定义一个is_type_of方法(或创建一个抽象的 ObjectType,您可以使用它已经实现的子类)。例如,这里是graphene-sqlalchemy实现is_type_of逻辑的代码,对于该graphene-django代码,这里是

@classmethod
def is_type_of(cls, root, info):
    if isinstance(root, SimpleLazyObject):
        root._setup()
        root = root._wrapped
    if isinstance(root, cls):
        return True
    if not is_valid_django_model(type(root)):
        raise Exception((
            'Received incompatible instance "{}".'
        ).format(root))

    model = root._meta.model._meta.concrete_model
    return model == cls._meta.model
于 2018-03-15T07:04:22.433 回答