Django 模型对象和石墨烯 get_node

Posted

技术标签:

【中文标题】Django 模型对象和石墨烯 get_node【英文标题】:Django model objects and Graphene get_node 【发布时间】:2018-06-28 22:27:52 【问题描述】:

到目前为止,我可以在不需要DjangoObjectType 的情况下使用 Graphene。我尽量避免它,因为我不打算离我的 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 实际上是“Test”。

有效的解决方案:

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

但是,我非常怀疑 Graphene 能为我做的只是这些。我真的必须将真实数据对象包装到HouseholdNode 中吗?我已经有了resolve函数,不能直接用吗?

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

【问题讨论】:

This issue 在 Github 上是相关的。 【参考方案1】:

抽象类型(如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 的用户定义子类,继承自具有is_type_of = Nonegraphene.types.objecttype.ObjectType。因此,您会得到GraphQLError,因为没有解析任何类型。

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

@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

【讨论】:

以上是关于Django 模型对象和石墨烯 get_node的主要内容,如果未能解决你的问题,请参考以下文章

聚合石墨烯/django 查询中的字段

Django 石墨烯中继限制对用户拥有的对象的查询

将 json 模型字段与 django 石墨烯一起使用

Django 石墨烯,按对象过滤

石墨烯和 Django 关于关系

石墨烯 django 继电器:继电器变换错误