如何解析graphene.Union Type?

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

我想创建两个现有类型(FirstType 和 SecondType)的 UnionType(graphene.Union) 并能够解析此联合类型的查询。


架构

    class FirstType(DjangoObjectType):
        class Meta:
            model = FirstModel

    class SecondType(DjangoObjectType):
        class Meta:
            model = SecondModel

    class UnionType(graphene.Union):
        class Meta:
            types = (FirstType, SecondType)

因此,使用此模式,我想使用某个列表 [pks] 中的 pk 查询 FirstType 和 SecondType 中的所有对象

    query {
        all_items(pks: [1,2,5,7]){
          ... on FirstType{
             pk,
             color, 
          }

          ... on SecondType{       
             pk,        
             size,
          }
        }
     }

来自 FirstType 的 PK 通常不在 SecondType 中。

我尝试了下面的方法

    def resolve_items(root, info, ids):
        queryset1 = FirstModel.objects.filter(id__in=pks)
        queryset2 = SecondModel.objects.filter(id__in=pks)
        return queryset1 | queryset2

但它给出了一个错误:“无法组合两个不同基础模型上的查询。”

我期望查询得到以下答复:

    { 'data':
        {'all_items':[
           {'pk': 1,
            'color': blue
           },
           {'pk': 2,
            'size': 50.0
           },
           ...
          ]}
     }

那么解析器应该是什么样子?

graphql graphene-django
2个回答
9
投票

关于联合类型的石墨烯文档非常稀疏。这是如何正确执行此操作的工作示例:

from graphene import ObjectType, Field, List, String, Int, Union

mock_data = {
    "episode": 3,
    "characters": [
        {
            "type": "Droid",
            "name": "R2-D2",
            "primaryFunction": "Astromech"
        },
        {
            "type": "Human",
            "name": "Luke Skywalker",
            "homePlanet": "Tatooine"
        },
        {
            "type": "Starship",
            "name": "Millennium Falcon",
            "length": 35
        }
    ]
}


class Human(ObjectType):
    name = String()
    homePlanet = String()


class Droid(ObjectType):
    name = String()
    primaryFunction = String()


class Starship(ObjectType):
    name = String()
    length = Int()


class Character(Union):
    class Meta:
        types = (Human, Droid, Starship)

    @classmethod
    def resolve_type(cls, instance, info):
        if instance["type"] == "Human":
            return Human
        if instance["type"] == "Droid":
            return Droid
        if instance["type"] == "Starship":
            return Starship


class RootQuery(ObjectType):
    result = Field(SearchResult)

    def resolve_result(_, info):
        return mock_data

然后,对于像

这样的查询
  query Humans {
    result {
      episode
      characters {
        ... on Droid {
          name
        }
        ... on Starship {
          name
        }
        ... on Human {
          name
        }
      }
    }
  }

它返回正确的结果。


5
投票

好吧,所以我太专注于合并查询集,而没有注意到我可以简单地返回一个列表。

所以这里的解决方案给了我我正在寻找的答案:

def resolve_items(root, info, ids):
    items = []
    queryset1 = FirstModel.objects.filter(id__in=pks)
    items.extend(queryset1)
    queryset2 = SecondModel.objects.filter(id__in=pks)
    items.extend(queryset2)
    return items
© www.soinside.com 2019 - 2024. All rights reserved.