嵌套对象的突变

问题描述 投票:0回答:1

我正在尝试为“复杂”对象实现 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)

但我不确定这是正确的方法。

所以请建议启动嵌套结构的正确方法。

python graphql graphene-python
1个回答
0
投票

您使用的是哪个版本的石墨烯?看起来用于 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",
                }
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.