# ObjectType

A Graphene ObjectType is the building block used to define the relationship between Fields in your Schema and how their data is retrieved.

The basics:

- Each ObjectType is a Python class that inherits from `graphene.ObjectType`.

- Each attribute of the ObjectType represents a `Field`.

- Each `Field` has a resolver method to fetch data (or Default Resolver).

## Quick example

This example model defines a Person, with a first and a last name:

    from graphene import ObjectType, String

    class Person(ObjectType):
        first_name = String()
        last_name = String()
        full_name = String()

        def resolve_full_name(parent, info):
            return f"{parent.first_name} {parent.last_name}"

This ObjectType defines the field first_name, last_name, and full_name. Each field is specified as a class attribute, and each attribute maps to a Field. Data is fetched by our `resolve_full_name` resolver method for `full_name` field and the Default Resolver for other fields.

The above `Person` ObjectType has the following schema representation:

    type Person {
      firstName: String
      lastName: String
      fullName: String
    }

## Resolvers

A Resolver is a method that helps us answer Queries by fetching data for a Field in our Schema.

Resolvers are lazily executed, so if a field is not included in a query, its resolver will not be executed.

Each field on an ObjectType in Graphene should have a corresponding resolver method to fetch data. This resolver method should match the field name. For example, in the `Person` type above, the `full_name` field is resolved by the method `resolve_full_name`.

Each resolver method takes the parameters:

- Parent Value Object (parent) for the value object use to resolve most fields

- GraphQL Execution Info (info) for query and schema meta information and per-request context

- GraphQL Arguments (**kwargs) as defined on the Field.

### Resolver Parameters

#### Parent Value Object (parent)

This parameter is typically used to derive the values for most fields on an ObjectType.

The first parameter of a resolver method (parent) is the value object returned from the resolver of the parent field. If there is no parent field, such as a root Query field, then the value for parent is set to the `root_value` configured while executing the query (default `None`). See Executing a query for more details on executing queries.

##### Resolver example

If we have a schema with Person type and one field on the root query.

    from graphene import ObjectType, String, Field

    def get_human(name):
        first_name, last_name = name.split()
        return Person(first_name, last_name)

    class Person(ObjectType):
        full_name = String()

        def resolve_full_name(parent, info):
            return f"{parent.first_name} {parent.last_name}"

    class Query(ObjectType):
        me = Field(Person)

        def resolve_me(parent, info):
            # returns an object that represents a Person
            return get_human(name="Luke Skywalker")

When we execute a query against that schema.

    schema = Schema(query=Query)

    query_string = "{ me { fullName } }"
    result = schema.execute(query_string)

    assert result.data["me"] == {"fullName": "Luke Skywalker"}

Then we go through the following steps to resolve this query:

- `parent` is set with the root_value from query execution (None).

- `Query.resolve_me` called with `parent` None which returns a value object `Person("Luke", "Skywalker")`.

- This value object is then used as `parent` while calling `Person.resolve_full_name` to resolve the scalar String value “Luke Skywalker”.

- The scalar value is serialized and sent back in the query response.

Each resolver returns the next Parent Value Object (parent) to be used in executing the following resolver in the chain. If the Field is a Scalar type, that value will be serialized and sent in the Response. Otherwise, while resolving Compound types like ObjectType, the value be passed forward as the next Parent Value Object (parent).

##### Naming convention

This Parent Value Object (parent) is sometimes named `obj`, `parent`, or `source` in other GraphQL documentation. It can also be named after the value object being resolved (ex. `root` for a root Query or Mutation, and `person` for a Person value object). Sometimes this argument will be named `self` in Graphene code, but this can be misleading due to Implicit staticmethod while executing queries in Graphene.

#### GraphQL Execution Info (info)

The second parameter provides two things:

- reference to meta information about the execution of the current GraphQL Query (fields, schema, parsed query, etc.)

- access to per-request `context` which can be used to store user authentication, data loader instances or anything else useful for resolving the query.

Only context will be required for most applications. See Context for more information about setting context.

#### GraphQL Arguments (**kwargs)

Any arguments that a field defines gets passed to the resolver function as keyword arguments. For example:

    from graphene import ObjectType, Field, String

    class Query(ObjectType):
        human_by_name = Field(Human, name=String(required=True))

        def resolve_human_by_name(parent, info, name):
            return get_human(name=name)

You can then execute the following query:

    query {
        humanByName(name: "Luke Skywalker") {
            firstName
            lastName
        }
    }

Note: There are several arguments to a field that are “reserved” by Graphene (see Fields (Mounted Types)). You can still define an argument that clashes with one of these fields by using the `args` parameter like so:

    from graphene import ObjectType, Field, String

    class Query(ObjectType):
        answer = String(args={'description': String()})

        def resolve_answer(parent, info, description):
            return description

### Convenience Features of Graphene Resolvers

#### Implicit staticmethod

One surprising feature of Graphene is that all resolver methods are treated implicitly as staticmethods. This means that, unlike other methods in Python, the first argument of a resolver is never `self` while it is being executed by Graphene. Instead, the first argument is always Parent Value Object (parent). In practice, this is very convenient as, in GraphQL, we are almost always more concerned with the using the parent value object to resolve queries than attributes on the Python object itself.

The two resolvers in this example are effectively the same.

    from graphene import ObjectType, String

    class Person(ObjectType):
        first_name = String()
        last_name = String()

        @staticmethod
        def resolve_first_name(parent, info):
            '''
            Decorating a Python method with `staticmethod` ensures that `self` will not be provided as an
            argument. However, Graphene does not need this decorator for this behavior.
            '''
            return parent.first_name

        def resolve_last_name(parent, info):
            '''
            Normally the first argument for this method would be `self`, but Graphene executes this as
            a staticmethod implicitly.
            '''
            return parent.last_name

        # ...

If you prefer your code to be more explicit, feel free to use `@staticmethod` decorators. Otherwise, your code may be cleaner without them!

#### Default Resolver

If a resolver method is not defined for a Field attribute on our ObjectType, Graphene supplies a default resolver.

If the Parent Value Object (parent) is a dictionary, the resolver will look for a dictionary key matching the field name. Otherwise, the resolver will get the attribute from the parent value object matching the field name.

    from collections import namedtuple

    from graphene import ObjectType, String, Field, Schema

    PersonValueObject = namedtuple("Person", ["first_name", "last_name"])

    class Person(ObjectType):
        first_name = String()
        last_name = String()

    class Query(ObjectType):
        me = Field(Person)
        my_best_friend = Field(Person)

        def resolve_me(parent, info):
            # always pass an object for `me` field
            return PersonValueObject(first_name="Luke", last_name="Skywalker")

        def resolve_my_best_friend(parent, info):
            # always pass a dictionary for `my_best_fiend_field`
            return {"first_name": "R2", "last_name": "D2"}

    schema = Schema(query=Query)
    result = schema.execute('''
        {
            me { firstName lastName }
            myBestFriend { firstName lastName }
        }
    ''')
    # With default resolvers we can resolve attributes from an object..
    assert result.data["me"] == {"firstName": "Luke", "lastName": "Skywalker"}

    # With default resolvers, we can also resolve keys from a dictionary..
    assert result.data["myBestFriend"] == {"firstName": "R2", "lastName": "D2"}

### Advanced

#### GraphQL Argument defaults

If you define an argument for a field that is not required (and in a query execution it is not provided as an argument) it will not be passed to the resolver function at all. This is so that the developer can differentiate between a `undefined` value for an argument and an explicit `null` value.

For example, given this schema:

    from graphene import ObjectType, String

    class Query(ObjectType):
        hello = String(required=True, name=String())

        def resolve_hello(parent, info, name):
            return name if name else 'World'

And this query:

    query {
        hello
    }

An error will be thrown:

    TypeError: resolve_hello() missing 1 required positional argument: 'name'

You can fix this error in several ways. Either by combining all keyword arguments into a dict:

    from graphene import ObjectType, String

    class Query(ObjectType):
        hello = String(required=True, name=String())

        def resolve_hello(parent, info, **kwargs):
            name = kwargs.get('name', 'World')
            return f'Hello, {name}!'

Or by setting a default value for the keyword argument:

    from graphene import ObjectType, String

    class Query(ObjectType):
        hello = String(required=True, name=String())

        def resolve_hello(parent, info, name='World'):
            return f'Hello, {name}!'

One can also set a default value for an Argument in the GraphQL schema itself using Graphene!

    from graphene import ObjectType, String

    class Query(ObjectType):
        hello = String(
            required=True,
            name=String(default_value='World')
        )

        def resolve_hello(parent, info, name):
            return f'Hello, {name}!'

#### Resolvers outside the class

A field can use a custom resolver from outside the class:

    from graphene import ObjectType, String

    def resolve_full_name(person, info):
        return f"{person.first_name} {person.last_name}"

    class Person(ObjectType):
        first_name = String()
        last_name = String()
        full_name = String(resolver=resolve_full_name)

#### Instances as value objects

Graphene `ObjectType`s can act as value objects too. So with the previous example you could use `Person` to capture data for each of the ObjectType’s fields.

    peter = Person(first_name='Peter', last_name='Griffin')

    peter.first_name  # prints "Peter"
    peter.last_name  # prints "Griffin"

#### Field camelcasing

Graphene automatically camelcases fields on ObjectType from `field_name` to `fieldName` to conform with GraphQL standards. See Auto camelCase field names for more information.

## ObjectType Configuration - Meta class

Graphene uses a Meta inner class on ObjectType to set different options.

### GraphQL type name

By default the type name in the GraphQL schema will be the same as the class name that defines the `ObjectType`. This can be changed by setting the `name` property on the `Meta` class:

    from graphene import ObjectType

    class MyGraphQlSong(ObjectType):
        class Meta:
            name = 'Song'

### GraphQL Description

The schema description of an ObjectType can be set as a docstring on the Python object or on the Meta inner class.

    from graphene import ObjectType

    class MyGraphQlSong(ObjectType):
        ''' We can set the schema description for an Object Type here on a docstring '''
        class Meta:
            description = 'But if we set the description in Meta, this value is used instead'

### Interfaces & Possible Types

Setting `interfaces` in Meta inner class specifies the GraphQL Interfaces that this Object implements.

Providing `possible_types` helps Graphene resolve ambiguous types such as interfaces or Unions.

See Interfaces for more information.

    from graphene import ObjectType, Node

    Song = namedtuple('Song', ('title', 'artist'))

    class MyGraphQlSong(ObjectType):
        class Meta:
            interfaces = (Node, )
            possible_types = (Song, )