Graphene Documentation

repository·master·Indexed 27 days ago

https://github.com/graphql-python/graphene

An opinionated Python library for building GraphQL schemas and types. Graphene is data-agnostic, supporting SQL (Django, SQLAlchemy), Mongo, and custom Python objects, with built-in support for Relay. It provides core classes for ObjectTypes, Mutations, and Scalars, as well as tools for execution metadata, middleware, query validation, and batching via DataLoader.

Tokens
17.9K
Snippets
68
Records
93
Agent score
93%

What's inside Graphene

  1. Explore Graphene integrations

    master

    Graphene provides several official and community integrations for popular web frameworks and ORMs to facilitate building GraphQL APIs. Available integrations include:

    • Django: Graphene-Django
    • Flask: Flask-Graphql
    • SQLAlchemy: Graphene-SQLAlchemy
    • MongoDB: Graphene-Mongo
    • Starlette: Native support via Starlette
    • FastAPI: Native support via FastAPI
  2. Define and implement GraphQL Interfaces

    master

    An Interface is an abstract type that defines a set of fields that implementing types must include. To create an interface, inherit from graphene.Interface. To implement an interface in an ObjectType, include the interface in the interfaces tuple within the Meta inner class.

    Implementing an interface allows you to return different object types from a single field, provided they all satisfy the interface's field requirements. You can query interface fields directly or use inline fragments (... on TypeName) to access type-specific fields.

    import graphene
    
    # 1. Define the Interface
    class Character(graphene.Interface):
        id = graphene.ID(required=True)
        name = graphene.String(required=True)
        friends = graphene.List(lambda: Character)
    
    # 2. Implement the Interface in ObjectTypes
    class Human(graphene.ObjectType):
        class Meta:
            interfaces = (Character,)
    
        starships = graphene.List(Starship)
        home_planet = graphene.String()
    
    class Droid(graphene.ObjectType):
        class Meta:
            interfaces = (Character,)
    
        primary_function = graphene.String()
    
    # 3. Use the Interface in a Query
    class Query(graphene.ObjectType):
        hero = graphene.Field(Character, required=True, episode=graphene.Int(required=True))
    
        def resolve_hero(root, info, episode):
            if episode == 5:
                return get_human(name='Luke Skywalker')
            return get_droid(name='R2-D2')
    
    schema = graphene.Schema(query=Query, types=[Human, Droid])
  3. Update Mutation.mutate signature

    master

    The mutate method in Mutation classes is no longer a @classmethod. It now receives (root, info, **kwargs) and you can access declared arguments directly as keyword arguments.

    # Before 2.0
    class SomeMutation(Mutation):
        @classmethod
        def mutate(cls, instance, args, context, info):
            ...
    
    # With 2.0
    class SomeMutation(Mutation):
        class Arguments:
            first_name = String(required=True)
            last_name = String(required=True)
    
        def mutate(root, info, first_name, last_name):
            ...
  4. Adjust Middleware for Graphene 2.0+

    master

    If you implement custom middleware, you must update the resolve method signature to use (self, next_mw, root, info, **args) and access context via info.context.

    # With 2.0
    class MyGrapheneMiddleware(object):
        def resolve(self, next_mw, root, info, **args):
            context = info.context
            # ... middleware logic ...
            return next_mw(root, info, **args)
  5. Create custom Relay Connections

    master

    To create a custom Connection type in Graphene, subclass relay.Connection. You can define extra fields on the Connection itself and extra fields on the Connection Edge by defining an inner Edge class.

    When you subclass Connection, the resulting class automatically includes a pageInfo field and an edges field. The edges field contains a list of the defined Edge objects, each of which includes a node field pointing to the underlying node type specified in Connection.Meta.node.

    class ShipConnection(Connection):
        extra = String()
    
        class Meta:
            node = Ship
    
        class Edge:
            other = String()
  6. Define an ObjectType in Graphene

    master

    An ObjectType is a Python class that inherits from graphene.ObjectType. It serves as the building block for your schema, defining the relationship between fields and how their data is retrieved. Each attribute defined on the class represents a GraphQL Field.

    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}"
  7. Implement Relay mutations with ClientIDMutation

    master

    To satisfy Relay's requirements for mutations, subclass relay.ClientIDMutation. This automatically manages the input/output structure required by Relay. Define an inner Input class for the mutation arguments and implement the mutate_and_get_payload class method to handle the business logic. The method should return an instance of the mutation class containing the desired return fields.

    class IntroduceShip(relay.ClientIDMutation):
    
        class Input:
            ship_name = graphene.String(required=True)
            faction_id = graphene.String(required=True)
    
        ship = graphene.Field(Ship)
        faction = graphene.Field(Faction)
    
        @classmethod
        def mutate_and_get_payload(cls, root, info, **input):
            ship_name = input.ship_name
            faction_id = input.faction_id
            ship = create_ship(ship_name, faction_id)
            faction = get_faction(faction_id)
            return IntroduceShip(ship=ship, faction=faction)
  8. Implement the Relay Node Interface

    master

    To support the Relay specification, you can use the relay.Node interface. Any ObjectType that inherits from relay.Node must implement a get_node class method. This method is responsible for retrieving a specific object instance using a provided id.

    When using relay.Node, the id returned in queries is a base64 encoded string containing both the type name and the object's internal ID (e.g., Ship:1 becomes U2hpcDox).

    class Ship(graphene.ObjectType):
        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)
  9. Create Custom Nodes with custom ID encoding

    master

    If you need to customize how global IDs are encoded or decoded, you can subclass Node.

    • Override to_global_id(type_, id) to define how the type name and ID are combined.
    • Override get_node_from_global_id(info, global_id, only_type=None) to define how to resolve an object from an encoded ID.

    When implementing get_node_from_global_id, you can use the only_type argument to validate that the decoded type matches the expected GraphQL type.

    class CustomNode(Node):
    
        class Meta:
            name = 'Node'
    
        @staticmethod
        def to_global_id(type_, id):
            return f"{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)