Graphene: Error implementing sample mutation from the docs

Created on 17 Jan 2017  路  3Comments  路  Source: graphql-python/graphene

I am trying to get familiar with the graphene library with the sample code from the docs. This is the code I am writing in the graphene-playground :

import graphene

class Person(graphene.ObjectType):
    name = graphene.String()

class CreatePerson(graphene.ObjectType):
    class Input:
        name = graphene.String()
    ok = graphene.Boolean()
    person = graphene.Field(lambda: Person)

    def mutate(self,args,context,info):
        person = Person(name = args.get('name'))
        ok = True
        return CreatePerson(person=person, ok=ok)

class MyMutations(graphene.ObjectType):
    create_person = CreatePerson.Field()

class Query(graphene.ObjectType):
    hello = graphene.String()
    test = graphene.Int()

    def resolve_hello(self, args, context, info):
        return 'World'

    def resolve_test(self, args, context, info):
        return 3

schema = graphene.Schema(query=Query,mutation=MyMutations)

I am getting an error in the class MyMutations's create_person = CreatePerson.Field() line. I get an error saying :

AttributeError: type object 'CreatePerson' has no attribute 'Field'

I do not know if I am missing something or the example is not working actually. If anyone would be kind enough to help me with explanation, I would be grateful 馃檪

Most helpful comment

@ghoshabhi, I had similar issues while trying to run the example from the doc. Finally, this is what worked for me:

# schema.py (courses app)

class CreateTeacher(graphene.Mutation):
    class Input:
        name = graphene.String()
        email = graphene.String()

    teacher = graphene.Field(TeacherNode)

    @classmethod
    def mutate(self, cls, input, context, info):
        name = input.get('name')
        email = input.get('email')

        teacher = Teacher(name=name, email=email)
        teacher.save()
        return CreateTeacher(teacher=teacher)

class CourseMutations(AbstractType):
    create_teacher = CreateTeacher.Field()

And then:

# schema.py (project level)
class AllMutations(courses.schema.CourseMutations, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query, mutation=AllMutations)

So I can execute:

mutation{
  createTeacher(name: "Mace Windu", email:"[email protected]"){
    teacher{
      id
      name
      email
    }
  }
}

Though this code works, I don't know if it's 100% correct, I'm also new to Graphene.

All 3 comments

In the docs, CreatePerson is a Mutation, not an ObjectType. ObjectType has no Field() method. You can create a field from an ObjectType with graphene.Field(...), but I don't think that's what you meant to do.

class CreatePerson(graphene.Mutation):
    class Input:
        name = graphene.String()

    ok = graphene.Boolean()
    person = graphene.Field(lambda: Person)

    def mutate(self, args, context, info):
        person = Person(name=args.get('name'))
        ok = True
        return CreatePerson(person=person, ok=ok)

@ghoshabhi, I had similar issues while trying to run the example from the doc. Finally, this is what worked for me:

# schema.py (courses app)

class CreateTeacher(graphene.Mutation):
    class Input:
        name = graphene.String()
        email = graphene.String()

    teacher = graphene.Field(TeacherNode)

    @classmethod
    def mutate(self, cls, input, context, info):
        name = input.get('name')
        email = input.get('email')

        teacher = Teacher(name=name, email=email)
        teacher.save()
        return CreateTeacher(teacher=teacher)

class CourseMutations(AbstractType):
    create_teacher = CreateTeacher.Field()

And then:

# schema.py (project level)
class AllMutations(courses.schema.CourseMutations, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query, mutation=AllMutations)

So I can execute:

mutation{
  createTeacher(name: "Mace Windu", email:"[email protected]"){
    teacher{
      id
      name
      email
    }
  }
}

Though this code works, I don't know if it's 100% correct, I'm also new to Graphene.

@ghoshabhi, I put together a second example, this time using ClientIDMutation:

class CreateCourse(graphene.ClientIDMutation):
    class Input:
        name = graphene.String()
        summary = graphene.String()
        teacher_id = graphene.String(required=True)

    course = graphene.Field(CourseNode)

    @classmethod
    def mutate_and_get_payload(cls, input, context, info):
        name = input.get('name')
        summary = input.get('summary')
        teacher_id = input.get("teacher_id")
        try:
            teacher_id = int(teacher_id)
        except ValueError:
            try:
                _type, teacher_id = Node.from_global_id(input.get("teacher_id"))
                assert _type == 'TeacherNode', 'Found {} instead of teacher'.format(_type)
                teacher_id = int(teacher_id)
            except:
                raise Exception("Received Invalid Teacher id: {}".format(teacher_id))

        teacher = Teacher._meta.model.objects.get(id=teacher_id)
        course = Course(name=name, summary=summary, teacher=teacher)
        course.save()
        return CreateCourse(course=course)


class CourseMutations(AbstractType):
   # ...
    create_course = CreateCourse.Field()

To execute this kind of mutations you need to pass an input argument

mutation {
  createCourse(input: {name: "Testing Course", summary: "the summary", teacherId: "VGVhY2hlck5vZGU6MQ=="}) {
    course {
      name
      teacher {
        name
      }
    }
  }
}

I hope this helps.

Was this page helpful?
0 / 5 - 0 ratings