Mutations¶
A Mutation is a special ObjectType that also defines an Input.
Quick example¶
This example defines a Mutation:
import graphene
class CreatePerson(graphene.Mutation):
class Arguments:
name = graphene.String()
ok = graphene.Boolean()
person = graphene.Field(lambda: Person)
def mutate(self, info, name):
person = Person(name=name)
ok = True
return CreatePerson(person=person, ok=ok)
person and ok are the output fields of the Mutation when it is resolved.
Arguments attributes are the arguments that the Mutation
CreatePerson
needs for resolving, in this case name will be the
only argument for the mutation.
mutate is the function that will be applied once the mutation is called.
So, we can finish our schema like this:
# ... the Mutation Class
class Person(graphene.ObjectType):
name = graphene.String()
age = graphene.Int()
class MyMutations(graphene.ObjectType):
create_person = CreatePerson.Field()
# We must define a query for our schema
class Query(graphene.ObjectType):
person = graphene.Field(Person)
schema = graphene.Schema(query=Query, mutation=MyMutations)
Executing the Mutation¶
Then, if we query (schema.execute(query_str)
) the following:
mutation myFirstMutation {
createPerson(name:"Peter") {
person {
name
}
ok
}
}
We should receive:
{
"createPerson": {
"person" : {
"name": "Peter"
},
"ok": true
}
}
InputFields and InputObjectTypes¶
InputFields are used in mutations to allow nested input data for mutations
To use an InputField you define an InputObjectType that specifies the structure of your input data
import graphene
class PersonInput(graphene.InputObjectType):
name = graphene.String(required=True)
age = graphene.Int(required=True)
class CreatePerson(graphene.Mutation):
class Arguments:
person_data = PersonInput(required=True)
person = graphene.Field(Person)
@staticmethod
def mutate(root, info, person_data=None):
person = Person(
name=person_data.name,
age=person_data.age
)
return CreatePerson(person=person)
Note that name and age are part of person_data now
Using the above mutation your new query would look like this:
mutation myFirstMutation {
createPerson(personData: {name:"Peter", age: 24}) {
person {
name,
age
}
}
}
InputObjectTypes can also be fields of InputObjectTypes allowing you to have as complex of input data as you need
import graphene
class LatLngInput(graphene.InputObjectType):
lat = graphene.Float()
lng = graphene.Float()
#A location has a latlng associated to it
class LocationInput(graphene.InputObjectType):
name = graphene.String()
latlng = graphene.InputField(LatLngInput)
Output type example¶
To return an existing ObjectType instead of a mutation-specific type, set the Output attribute to the desired ObjectType:
import graphene
class CreatePerson(graphene.Mutation):
class Arguments:
name = graphene.String()
Output = Person
def mutate(self, info, name):
return Person(name=name)
Then, if we query (schema.execute(query_str)
) the following:
mutation myFirstMutation {
createPerson(name:"Peter") {
name
__typename
}
}
We should receive:
{
"createPerson": {
"name": "Peter",
"__typename": "Person"
}
}