覆盖石墨烯中的 django 选择输出
Overwrite django choices output in graphene
我正在使用 graphene
和 graphene-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 的更多信息。
我正在使用 graphene
和 graphene-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 的更多信息。