Reputation: 4743
I've defined Django models with fields containing text choices corresponding to enums. The GraphQL API provides mutations (which are not derived from models directly) with arguments of type enum which shall accept the same values as the models only. How can I get rid of my dublication?
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)
Upvotes: 6
Views: 4253
Reputation: 80
extend your graphene.Enum
instances with the class below
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
Your Example Enum will look like the one below
# import the EnumChoices class above
from graphene import Enum
class YourExampleChoices(EnumChoices, Enum):
BAD = "Bad"
MEH = "Meh"
NORMAL = "Normal"
LIKE = "Like"
LOVE = "Love"
Your example graphene.types.InputObjectType
will look like the one below
# import the YourExampleChoices class above
from graphene.types import InputObjectType
class YourExampleChoicesMutationInput(InputObjectType):
choice = YourExampleChoices(required=True)
Your example graphene.Mutation
will look like the one below
# 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
Your Django model will look like the one below
# 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_
)
Upvotes: 1
Reputation: 13640
If you'd like to use Enums in custom mutations then, you could use graphine.Enum
like this.
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)
I recommend to use PermisionEnum(required=True)
approach because with it PermisionEnum
class can be reuse across different mutations. This is not possible when you declare enums as I do it with scope
filed!
Upvotes: 1
Reputation: 403
You can use graphene.Enum.from_enum()
.
This function can convert normal Enum
type to graphene.Enum
.
Do notice that models.TextChoices
is only available for Dajango version above 3.0
models.py (for Django version >= 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 (for Django version < 3.0)
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)
Upvotes: 13