我正在尝试为“复杂”对象实现 GraphQL 突变。假设我们有一个具有三个字段的
Contact
:firstName
、lastName
和 address
,它是具有一个字段的对象 street
:
这是我的python方案实现:
class Address(graphene.ObjectType):
street = graphene.String(description='Street Name')
class AddressInput(graphene.InputObjectType):
street = graphene.String(description='Street Name', required=True)
class Contact(graphene.ObjectType):
first_name = graphene.String(description='First Name')
last_name = graphene.String(description='Last Name')
address = graphene.Field(Address, description='Contact address')
class ContactInput(graphene.InputObjectType):
first_name = graphene.String(description='First Name', required=True)
last_name = graphene.String(description='Last Name', required=True)
address = AddressInput(description='Contact address', required=True)
class CreateContact(graphene.Mutation):
class Input:
contact = ContactInput()
contact = graphene.Field(Contact, description='Created Contact object')
@staticmethod
def mutate(instance, args, context, info):
contact = Contact(**args['contact'])
return CreateContact(contact=contact)
当我运行此查询时:
mutation CreateContact($contact: ContactInput!) {
createContact(contact: $contact) {
contact {
firstName
address {
street
}
}
}
}
具有以下变量:
{
"contact": {
"address": {
"street": "Bond Blvd"
},
"firstName": "John",
"lastName": "Doe"
}
}
我得到以下结果:
{
"createContact": {
"contact": {
"address": {
"street": null
},
"firstName": "John"
}
}
}
如您所见,结果中的
street
字段为 null
。
如果我将
mutate
方法更改为如下所示,我可以获得我需要的东西:
@staticmethod
def mutate(instance, args, context, info):
args['contact']['address'] = Address(**args['contact']['address'])
contact = Contact(**args['contact'])
return CreateContact(contact=contact)
但我不确定这是正确的方法。
所以请建议启动嵌套结构的正确方法。
您使用的是哪个版本的石墨烯?看起来用于 Adress ObjectType 的默认解析器无法解析字典。
默认在石墨烯中https://docs.graphene-python.org/en/latest/types/objecttypes/#defaultresolver:
解析器将查找与字段名称匹配的字典键。否则,解析器将从与字段名称匹配的父值对象中获取属性
您可以尝试使用特定解析器配置 Address 类:
from graphene.types.resolver import dict_or_attr_resolver, dict_resolver
class Address(graphene.ObjectType):
street = graphene.String(description="Street Name")
class Meta:
default_resolver = dict_or_attr_resolver
另外,对于我来说,当前最新版本的石墨烯(3.3)以下工作正常:
class Address(graphene.ObjectType):
street = graphene.String(description="Street Name")
class AddressInput(graphene.InputObjectType):
street = graphene.String(description="Street Name", required=True)
class Contact(graphene.ObjectType):
first_name = graphene.String(description="First Name")
last_name = graphene.String(description="Last Name")
address = graphene.Field(Address, description="Contact address")
class ContactInput(graphene.InputObjectType):
first_name = graphene.String(description="First Name", required=True)
last_name = graphene.String(description="Last Name", required=True)
address = AddressInput(description="Contact address", required=True)
class CreateContact(graphene.Mutation):
class Input:
contact = ContactInput()
contact = graphene.Field(Contact, description="Created Contact object")
def mutate(root, info, **args):
contact = Contact(**args["contact"])
return CreateContact(contact=contact)
def test_resolver():
query = """
mutation CreateContact($contact: ContactInput!) {
createContact(contact: $contact) {
contact {
firstName
address {
street
}
}
}
}
"""
client = Client(schema)
response = client.execute(
query,
variables={
"contact": {
"address": {"street": "Bond Blvd"},
"firstName": "John",
"lastName": "Doe",
}
},
)
assert response == {
"data": {
"createContact": {
"contact": {
"address": {
"street": "Bond Blvd",
},
"firstName": "John",
}
}
}
}