I'm having trouble inheriting multiple mutations together in 1.0.
Previously was able to set up a (reusable mutation) like this:
class SimpleCreationMutation(relay.ClientIDMutation):
class Input:
name = graphene.String(required=True)
ok = graphene.Boolean()
@classmethod
def mutate_and_get_payload(cls, input, context, info):
model = cls.Config.model
name = input.get('name')
instance = model(name=name)
instance.save()
return cls(result=instance, ok=bool(instance.id))
class CreateTag(SimpleCreationMutation):
class Config:
model = Tag
result = graphene.Field(TagNode)
Now trying to call that mutation leads to this error:
"Argument \"input\" has invalid value {clientMutationId: \"test_mutation\", name: \"test_name\"}.\nIn field \"name\": Unknown field."
@morgante While I agree this should work, one thing you could do in the meantime is using the AbstractType as shown here: https://github.com/graphql-python/graphene/blob/master/graphene/relay/tests/test_mutation.py#L36
@Globegitter I actually _did_ try to use the AbstractType and it still didn't work. Like so:
class SimpleCreationMutation(AbstractType):
class Input:
name = graphene.String(required=True)
ok = graphene.Boolean()
@classmethod
def mutate_and_get_payload(cls, input, context, info):
model = cls.Config.model
name = input.get('name')
instance = model(name=name)
instance.save()
return cls(result=instance, ok=bool(instance.id))
class CreateTag(SimpleCreationMutation, relay.ClientIDMutation):
class Config:
model = Tag
result = graphene.Field(TagNode)
@morgante Did you ever find a way to make the class Input inheritable? I have a similar problem where I have a large number of CRUD mutations and I'd like to make the input shared between set and create mutations. I am successful at least sharing fields by inheriting from AbstractType just like the line ok = graphene.Boolean() in your example.
Hi @morgante . We're currently going through old issues that appear to have gone stale (ie. not updated in about the last 6 months) to try and clean up the issue tracker. If this is still important to you please comment and we'll re-open this.
Thanks!
I ended up with this pattern:
class AbstractCreateBaz(ObjectType):
class Arguments:
name = String()
result = List(String)
def create_baz_mutate(name):
# Put save code here
return AbstractCreateBaz(result=name)
class CreateFoo(Mutation, AbstractCreateBaz):
def mutate(self, info, name):
return create_baz_mutate('foo')
class CreateBar(Mutation, AbstractCreateBaz):
def mutate(self, info, name):
return create_baz_mutate('bar')
class BazMutations(ObjectType):
create_foo = CreateFoo.Field()
create_bar = CreateBar.Field()
It's a bit verbose, is there a better way?
Found yet another way:
Define the class dynamically.
def create_class(foo_id: str): # so I can create a slightly different kind of class every time
class CreateFoo(Mutation, AbstractCreateFoo):
def mutate(self, info, name):
# create code goes here
return AbstractCreateFoo(result=bar)
return type(foo_id, (CreateFoo,), {})
Hope this helps someone
Most helpful comment
@morgante Did you ever find a way to make the
class Inputinheritable? I have a similar problem where I have a large number of CRUD mutations and I'd like to make the input shared between set and create mutations. I am successful at least sharing fields by inheriting fromAbstractTypejust like the lineok = graphene.Boolean()in your example.