到目前为止,我能够在不需要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)
中吗?我已经有解决功能,不能简单地使用它们吗?
文档在这些方面非常缺乏,请赐教。
答案 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_types
是Node
的用户定义子类,继承自graphene.types.objecttype.ObjectType
{{}}}。因为没有解决任何类型,你得到is_type_of = None
。
解决方案是在对象类型上定义is_type_of
方法(或者创建一个抽象的ObjectType,您可以使用已经实现的方法对其进行子类化)。例如,graphene-sqlalchemy
中GraphQLError
实现了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