联合类型无法在运行时解析对象类型

2024-09-30 08:38:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Starlette和Graphene使用Python设置GraphQL服务器,遇到了一个无法解决的问题。Graphene Documentation没有详细介绍我正在尝试实现的联合类型。 我根据graphene文档设置了一个最小的示例,您可以运行它来复制这个问题

import os

import uvicorn
from graphene import ObjectType, Field, List, String, Int, Union
from graphene import Schema
from starlette.applications import Starlette
from starlette.graphql import GraphQLApp
from starlette.routing import Route

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()
    primary_function = String()


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


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


class SearchResult(ObjectType):
    characters = List(Characters)
    episode = Int()


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

    @staticmethod
    def resolve_result(_, info):
        return mock_data


graphql_app = GraphQLApp(schema=Schema(query=RootQuery))

routes = [
    Route("/graphql", graphql_app),
]

api = Starlette(routes=routes)

if __name__ == "__main__":
    uvicorn.run(api, host="127.0.0.1", port=int(os.environ.get("PORT", 8080)))

如果您随后转到http://localhost:8080/graphq并输入以下查询

query Humans{
  result {
    episode
    characters {
      ... on Human {
        name
      }
    }
  }
}

我得到这个错误

 {
    "data": {
        "result": {
            "episode": 3,
            "characters": null
        }
    },
    "errors": [
        {
            "message": "Abstract type Characters must resolve to an Object type at runtime for field SearchResult.characters with value \"[{'type': 'Droid', 'name': 'R2-D2', 'primaryFunction': 'Astromech'}, {'type': 'Human', 'name': 'Luke Skywalker', 'homePlanet': 'Tatooine'}, {'type': 'Starship', 'name': 'Millennium Falcon', 'length': 35}]\", received \"None\".",
            "locations": [
                {
                    "line": 4,
                    "column": 5
                }
            ]
        }
    ]
}

我现在被困在这里了。也许有人已经这样做了,可以帮忙吗如何在运行时解决此问题。我已经尝试过不同的方法,例如我更改了类字符根查询

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

    def __init__(self, data, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.data = data
        self.type = data.get("type")

    def resolve_type(self, info):
        if self.type == "Human":
            return Human
        if self.type == "Droid":
            return Droid
        if self.type == "Starship":
            return Starship


class RootQuery(ObjectType):
    result = Field(SearchResult)
    
    @staticmethod
    def resolve_result(_, info):
        return {**mock_data, "characters": [Character(character) for character in mock_data.get('characters')]}

导致

{
    "data": {
        "result": {
            "episode": 3,
            "characters": [
                {},
                {
                    "name": null
                },
                {}
            ]
        }
    }
}

任何想法都将不胜感激


Tags: namefromimportselfdatastringtyperesult
1条回答
网友
1楼 · 发布于 2024-09-30 08:38:11

jkimbo回答了问题here

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

注意,我只是返回mock_数据,并更新了resolve_type方法以根据数据进行切换。Union类型使用与接口相同的resolve_type方法来确定在运行时解析为哪种类型:https://docs.graphene-python.org/en/latest/types/interfaces/#resolving-data-objects-to-types

相关问题 更多 >

    热门问题