Graphene: Enums don't seem to work with mutations

Created on 8 Sep 2016  路  7Comments  路  Source: graphql-python/graphene

Passing in enum values as strings results in an error of the form: Argument "fieldName" has invalid value "MyEnumVal". Expected type "MyEnum", found "MyEnumVal".

I think passing in strings would be more reliable than integers (but neither one seems to work).

馃憖 more info needed

Most helpful comment

Just in case someone else comes to this issue and has an existing enum.Enum, here is sample code to use it in mutation without need to redefine it as graphene.Enum:

from enum import Enum
import graphene

class ShareTypes(Enum):
    public = 'PUBLIC'
    authority = 'AUTHORITY'
    users = 'USERS'

class DoSomething(graphene.Mutation):
    class Input:
        myEnum = graphene.Enum.from_enum(ShareTypes)(required=True)

    message = graphene.String()

    @classmethod
    def mutate(cls, instance, args, info):
        return DoSomething(message="Success!")

All 7 comments

Hi @markflorisson, could be possible to have a working example of the issue?

Here is a small example:

import graphene

class MyEnum(graphene.Enum):
    Foo = 0
    Bar = 1

class DoSomething(graphene.Mutation):
    class Input:
        myEnum = graphene.Field(MyEnum)

    message = graphene.String()

    @classmethod
    def mutate(cls, instance, args, info):
        return DoSomething(message="Success!")

class MyMutations(graphene.ObjectType):
    doSomething = graphene.Field(DoSomething)

schema = graphene.Schema(mutation=MyMutations)
print(schema.execute(
    """
    mutation {
        doSomething(myEnum:"Foo") {
            message
        }
    }
    """).errors)

Which gives: GraphQLError('Unknown argument "myEnum" on field "doSomething" of type "MyMutations".',).

It used to give something else, but I upgraded graphene to 1.0.dev, where even the basic mutation example from the website doesn't seem to work (http://graphene-python.org/docs/mutations/).

Oh ok, thanks for the example.

What is failing is Input requires a InputField instead of a Field.
You can also do this:

class DoSomething(graphene.Mutation):
    class Input:
        myEnum = MyEnum() # This will act as InputField automatically

    message = graphene.String()

    @classmethod
    def mutate(cls, instance, args, info):
        return DoSomething(message="Success!")

Hope this helps! Closing the issue, but feel free to comment and I will follow :)

Just in case someone else comes to this issue and has an existing enum.Enum, here is sample code to use it in mutation without need to redefine it as graphene.Enum:

from enum import Enum
import graphene

class ShareTypes(Enum):
    public = 'PUBLIC'
    authority = 'AUTHORITY'
    users = 'USERS'

class DoSomething(graphene.Mutation):
    class Input:
        myEnum = graphene.Enum.from_enum(ShareTypes)(required=True)

    message = graphene.String()

    @classmethod
    def mutate(cls, instance, args, info):
        return DoSomething(message="Success!")

This does not work if I use that enum in one of my model's fields. :|

Error: AssertionError: Found different types with the same name in the schema: MyEnum, MyEnum.

I guess the reason is that it is already in the registry.

To revive this issue and give a concrete example of the previous comment, I am using django and have a model with field

    state = models.CharField(max_length=255, choices=State.choices, default=State.PUBLISHED)

with my state enum being

class State(models.TextChoices):
    ARCHIVED = 'ARCHIVED'
    PUBLISHED = 'PUBLISHED'

then I use it in my mutation like so

class Whatever(graphene.Mutation):
    class Arguments(object):
        state = graphene.Enum.from_enum(State)(required=False)

I then get AssertionError: Found different types with the same name in the schema: State, State. when running tests or regularly running mutations. Would be really nice to not have to define these twice, any suggestions would be very appreciated! thanks

I'm having this same issue: mixing queries, mutations, enumerations and Django is messy. I'm on Django 2.x so I couldn't use TextChoices, but with some elbow grease, you can get something that everyone agrees on:

# ... in the Django file
class FooOrBar(Enum):
    FOO = "foo"
    BAR = "bar"

class AnObject(models.Model):
  foobar = models.CharField(
        max_length=3,
        choices=[
            (FooOrBar.FOO.value, "The Foo"),
            (FooOrBar.BAR.value, "The Bar"),
        ],
    )

# ... in the Graphene file

FooOrBar = graphene.Enum.from_enum(models.FooBar)

class AnObject(DjangoObjectModel):
  class Meta:
    model = models.AnObject
    fields = ["id"]

  # Use default resolver; this field just exists to redefine the type.
  foobar = graphene.NonNull(FooOrBar)

class MutateMyObject(graphene.Mutation):
  class Arguments:
    foobar = g.NonNull(FooOrBar)

More boilerplate than I was hoping, but it's pretty straightforward and there's only a couple of these in my project.

Was this page helpful?
0 / 5 - 0 ratings