如何将单个枚举用于 django 模型和 graphql 突变参数?
Posted
技术标签:
【中文标题】如何将单个枚举用于 django 模型和 graphql 突变参数?【英文标题】:How can I use a single enum for django model and graphql mutation arguments? 【发布时间】:2020-07-15 17:58:30 【问题描述】:我已经定义了 Django 模型,其字段包含对应于枚举的文本选择。 GraphQL API 提供了带有 enum 类型参数的突变(不是直接从模型派生的),它应该只接受与模型相同的值。我怎样才能摆脱我的重复?
models.py:
class SomeModel(models.Model):
class SomeEnum(models.TextChoices):
A = "A", _("Option A")
B = "B", _("Option B")
enum_field = models.CharField(
max_length=1,
choices=SomeEnum.choices,
default=SomeEnum.A,
)
schema.py:
class SomeEnumSchema(graphene.Enum):
A = "A"
B = "B"
class SomeMutation(graphene.Mutation):
class Arguments:
some_enum = SomeEnumSchema(required=True)
【问题讨论】:
我不知道 python ... 将值提取到某个基类,两者都通用 - 多重继承? 【参考方案1】:使用以下类扩展您的 graphene.Enum
实例
from inspect import getmembers, isroutine
class EnumChoices:
@classmethod
def choices(self):
attributes = getmembers(self, lambda a: not (isroutine(a)))
values = [(a[0], a[1]._value_) for a in attributes if hasattr(a[1], "_value_")]
return values
您的示例枚举将如下所示
# import the EnumChoices class above
from graphene import Enum
class YourExampleChoices(EnumChoices, Enum):
BAD = "Bad"
MEH = "Meh"
NORMAL = "Normal"
LIKE = "Like"
LOVE = "Love"
您的示例 graphene.types.InputObjectType
将如下所示
# import the YourExampleChoices class above
from graphene.types import InputObjectType
class YourExampleChoicesMutationInput(InputObjectType):
choice = YourExampleChoices(required=True)
您的示例 graphene.Mutation
将如下所示
# import the YourExampleChoicesMutationInput class above
import graphene
from graphene.types.mutation import Mutation
class YourExampleMutation(Mutation):
# make sure to define your mutation results fields
class Arguments:
input = YourExampleChoicesMutationInput(required=True)
def mutate(root, info, input):
# what do you want this mutation to do?
pass
您的 Django 模型将如下所示
# import the YourExampleChoices class above
# notice that `YourExampleChoices.choices()` is callable, this is slightly different from the `Textchoices.choices` which isn't callable
class YourExampleModel(TimestampBase):
choices = models.CharField(
max_length=6,
choices=YourExampleChoices.choices(),
default=YourExampleChoices.NORMAL._value_
)
【讨论】:
【参考方案2】:如果您想在自定义突变中使用 Enums,您可以像这样使用graphine.Enum
。
class PermisionEnum(graphene.Enum):
READ = "read"
WRITE = "write"
class SimpleModelMutation(graphene.Mutation):
class Arguments:
# reusable
permission = PermisionEnum(required=True)
# not reusable
scope = graphene.Enum('scope', [
("PERSONAL", "personal"),
("PROJECT", "project")
])(required=True)
我建议使用PermisionEnum(required=True)
方法,因为使用它PermisionEnum
类可以在不同的突变中重复使用。当您声明枚举时,这是不可能的,因为我使用 scope
归档!
【讨论】:
【参考方案3】:您可以使用graphene.Enum.from_enum()
。
该函数可以将普通的Enum
类型转换为graphene.Enum
。
请注意models.TextChoices
仅适用于 3.0 以上的 Dajango 版本
models.py(对于 Django 版本 >= 3.0)
from django.db import models
class SomeModel(models.Model):
class SomeEnum(models.TextChoices):
A = "A", _("Option A")
B = "B", _("Option B")
enum_field = models.CharField(
max_length=1,
choices=SomeEnum.choices,
default=SomeEnum.A,
)
models.py(适用于 Django 版本
from enum import Enum
class SomeEnum(Enum):
A = "A"
B = "B"
schema.py:
SomeEnumSchema = graphene.Enum.from_enum(SomeEnum)
class SomeMutation(graphene.Mutation):
class Arguments:
some_enum = SomeEnumSchema(required=True)
【讨论】:
对于 Django >= 3.0 版本的一个重要说明是每个枚举选项的类变量名称必须匹配元组的第一个元素。这意味着要使用 Option A 枚举的小写键,它必须写为a = "a", _("Option A")
以上是关于如何将单个枚举用于 django 模型和 graphql 突变参数?的主要内容,如果未能解决你的问题,请参考以下文章
Django/Python:如何将整数转换为等效的枚举字符串? [复制]