覆盖石墨烯中的 django 选择输出

Overwrite django choices output in graphene

我正在使用 graphenegraphene-django,但我在选择 IntegerField 时遇到了问题。 graphene创建一个Enum,如果值为1则输出"A_1"; "A_2"如果值为2,依此类推。示例:

# model
class Foo(models.Model):
    score = models.IntegerField(choices=((1, 1), (2, 2), (3, 3), (4, 4), (5, 5)))

# query

query {
    foo {
       score
    }
}

# response 

{
  "data": {
    "foo": {
      "source": "A_1"
    }
  }
}

我找到了一个转换选项值的函数。

def convert_choice_name(name):
    name = to_const(force_text(name))
    try:
        assert_valid_name(name)
    except AssertionError:
        name = "A_%s" % name
    return name

assert_valid_name 有这个正则表达式:

r'^[_a-zA-Z][_a-zA-Z0-9]*$'

因此,任何以数字开头的内容,都会将其转换为"A_..."。

如何覆盖此输出?

代码注释说

GraphQL serializes Enum values as strings, however internally Enums can be represented by any kind of type, often integers.

因此,对于您的特定情况,您将无法轻松地将线上值替换为整数。但是,如果字符串 ("A_1") 表示的实际值在内部和客户端仍然是一个整数(根据字段的描述值)可能并不重要。

一般来说,您可以通过定义一个枚举 class 并添加到 DjangoObjectType 的定义来用选项替换自动生成的字段。这是一个使用文档枚举示例的示例...

class Episode(graphene.Enum):
    NEWHOPE = 4
    EMPIRE = 5
    JEDI = 6

    @property
    def description(self):
        if self == Episode.NEWHOPE:
            return 'New Hope Episode'
        return 'Other episode'

然后您可以将其添加到您的 DjangoObjectType

class FooType(DjangoObjectType):
    score = Episode()
    class Meta:
        model = Foo

或者,如果您想获得额外的乐趣,您可以根据 Foo._meta.get_field('score').choices 中的字段选择动态生成 Enum 字段。参见 graphene_django.converter.convert_django_field_with_choices

我自己刚碰到这个,另一种方法是在 Meta 之外定义你的字段(使用 only_fields)作为一个 graphene.Int,然后你可以提供你自己的解析器函数并且只是return 字段的值,将以数字结尾。

我的代码片段(问题字段是 resource_type,即枚举):

class ResourceItem(DjangoObjectType):
    class Meta:
        model = Resource
        only_fields = (
            "id",
            "title",
            "description",
            "icon",
            "target",
            "session_reveal",
            "metadata",
            "payload",
        )

    resource_type = graphene.Int()

    def resolve_resource_type(self, info):
        return self.resource_type

您可以在您的 Graphene-Django 模型中将 convert_choices_to_enum 设置为 False,这将使它们保留为整数。

class FooType(DjangoObjectType):
    class Meta:
        model = Foo
        convert_choices_to_enum = False

有关设置 here 的更多信息。