Django模型对象和Graphene get_node

时间:2018-01-19 16:10:50

标签: python django graphql graphene-python

到目前为止,我能够在不需要DjangoObjectType的情况下使用石墨烯。我试图避免它,因为我不打算离我的Django模型类太近了。然而,在使用石墨烯实现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)

此操作失败,并显示以下错误:

  

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

“测试”直接来自Household的{​​{1}}函数。

接下来尝试:

__str__

@classmethod def get_node(cls, info, id): return cls(Household.objects.get(pk=id)) cls。然而,这会产生错误的结果:

HouseholdNode

该ID实际上是“测试”。

有效的解决方案:

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

然而,我非常怀疑这是石墨烯能为我做的全部。我真的必须将真实数据对象包装到 @classmethod def get_node(cls, info, id): household = Household.objects.get(pk=id) return cls(name=household.name) 中吗?我已经有解决功能,不能简单地使用它们吗?

文档在这些方面非常缺乏,请赐教。

1 个答案:

答案 0 :(得分: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_typesNode的用户定义子类,继承自graphene.types.objecttype.ObjectType {{}}}。因为没有解决任何类型,你得到is_type_of = None

解决方案是在对象类型上定义is_type_of方法(或者创建一个抽象的ObjectType,您可以使用已经实现的方法对其进行子类化)。例如,graphene-sqlalchemyGraphQLError实现了is_type_of逻辑,graphene-django实现了here is the code

@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