如何忽略传递给突变的未知参数?

时间:2019-11-12 10:55:20

标签: python django graphql graphene-python graphene-django

根据GraphQL规范https://graphql.github.io/graphql-spec/draft/#sec-Input-Objects

  

输入对象的文字或无序映射不得包含名称未由此输入对象类型的字段定义的任何条目,否则必须引发错误。

假设我有一个项目,该项目有一个名为“买方”的用户,其架构如下所示

type Buyer {
     id: ID!
     name: String!
     address: String!
     email: String!
}

现在我可以为其编写石墨烯架构了

class BuyerType(DjangoObjectType):
    class Meta:
        model = Buyer

为此做一个变异

class BuyerInput(graphene.InputObjectType):
    name = graphene.String(required=False, default_value='')
    address = graphene.String(required=False, default_value='')
    email = graphene.String(required=False, default_value='')


class BuyerMutation(graphene.Mutation):
    """
    API to create applicant
    """
    class Arguments:
        buyer_data = BuyerInput(required=True)


    buyer = graphene.Field(BuyerType)
    ok = graphene.Boolean()

    def mutate(self, info, buyer_data=None):
           buyer = Buyer(name=buyer.name, address=buyer.address, email=buyer.email)
           buyer.save()
           return BuyerMutation(buyer=buyer, ok=True)

并编写解析器功能以及查询和变异类。到目前为止,还很基本。

现在要创建一个新的买家,我将其称为突变

mutation {
   createBuyer(
           name: "New Buyer"
           address: "Earth"
           email: "abc@example.com"
  ) {
      ok
  }
}

但是,如果我通过另一个称为电话的字段

mutation {
   createBuyer(
           name: "New Buyer"
           address: "Earth"
           email: "abc@example.com"
           phone: 8541345474
  ) {
      ok
  }
}

出现Unknown field 'phone'错误,可以理解。

但是我想简化前端开发人员的流程。他们可以只传递一个包含这三个字段以及可能来自表单提交的其他参数的字典,而不是在mutation参数中提及每个字段,然后在后端读取该字典并仅提取我需要的字段,就像使用REST API一样。

如果可能的话,我该如何实现呢?

1 个答案:

答案 0 :(得分:0)

我们可以使用BuyerInput模块获取inspect的类属性,然后组装参数字典,以便它忽略不是此类属性的键。假设我们有一个字典,其中包含存储在变量createBuyer中的kwargs的参数,它看起来可能如下所示:

import inspect


members = inspect.getmembers(BuyerInput, lambda a: not(inspect.isroutine(a)))
attributes = [
    tup[0] 
    for tup in members 
    if not tup[0].startswith("_")
]

kwargs = {
    key: value
    for key, value in kwargs.items()
    if key in attributes
}