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(root, 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. This method is just a special resolver that we can change data within. It takes the same arguments as the standard query Resolver Parameters.
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)
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(root, info, name):
return Person(name=name)
Then, if we query (schema.execute(query_str)
) with the following:
mutation myFirstMutation {
createPerson(name:"Peter") {
name
__typename
}
}
We should receive:
{
"createPerson": {
"name": "Peter",
"__typename": "Person"
}
}