# Nodes

A `Node` is an Interface provided by `graphene.relay` that contains a single field `id` (which is a `ID!`). Any object that inherits from it has to implement a `get_node` method for retrieving a `Node` by an id.

## Quick example

Example usage (taken from the Starwars Relay example):

    class Ship(graphene.ObjectType):
        '''A ship in the Star Wars saga'''
        class Meta:
            interfaces = (relay.Node, )

        name = graphene.String(description='The name of the ship.')

        @classmethod
        def get_node(cls, info, id):
            return get_ship(id)

The `id` returned by the `Ship` type when you query it will be a scalar which contains enough info for the server to know its type and its id.

For example, the instance `Ship(id=1)` will return `U2hpcDox` as the id when you query it (which is the base64 encoding of `Ship:1`), and which could be useful later if we want to query a node by its id.

## Custom Nodes

You can use the predefined `relay.Node` or you can subclass it, defining custom ways of how a node id is encoded (using the `to_global_id` method in the class) or how we can retrieve a Node given a encoded id (with the `get_node_from_global_id` method).

Example of a custom node:

    class CustomNode(Node):

        class Meta:
            name = 'Node'

        @staticmethod
        def to_global_id(type, id):
            return '{}:{}'.format(type, id)

        @staticmethod
        def get_node_from_global_id(info, global_id, only_type=None):
            type, id = global_id.split(':')
            if only_type:
                # We assure that the node type that we want to retrieve
                # is the same that was indicated in the field type
                assert type == only_type._meta.name, 'Received not compatible node.'

            if type == 'User':
                return get_user(id)
            elif type == 'Photo':
                return get_photo(id)

The `get_node_from_global_id` method will be called when `CustomNode.Field` is resolved.

## Accessing node types

If we want to retrieve node instances from a `global_id` (scalar that identifies an instance by it’s type name and id), we can simply do `Node.get_node_from_global_id(info, global_id)`.

In the case we want to restrict the instance retrieval to a specific type, we can do: `Node.get_node_from_global_id(info, global_id, only_type=Ship)`. This will raise an error if the `global_id` doesn’t correspond to a Ship type.

## Node Root field

As is required in the Relay specification, the server must implement a root field called `node` that returns a `Node` Interface.

For this reason, `graphene` provides the field `relay.Node.Field`, which links to any type in the Schema which implements `Node`. Example usage:

    class Query(graphene.ObjectType):
        # Should be CustomNode.Field() if we want to use our custom Node
        node = relay.Node.Field()