Graphene Bundle API

flask_unchained.bundles.graphene

GrapheneBundle

The Graphene Bundle.

flask_unchained.bundles.graphene.config

Config

DevConfig

flask_unchained.bundles.graphene.hooks

RegisterGrapheneMutationsHook

Registers Graphene Mutations with the Graphene Bundle.

RegisterGrapheneQueriesHook

Registers Graphene Queries with the Graphene Bundle.

RegisterGrapheneRootSchemaHook

Creates the root graphene.Schema to register with Flask-GraphQL.

RegisterGrapheneTypesHook

Registers SQLAlchemyObjectTypes with the Graphene Bundle.

flask_unchained.bundles.graphene.object_types

QueriesObjectType

Base class for query schema definitions.

MutationsObjectType

Base class for mutation schema definitions.

SQLAlchemyObjectType

Base class for SQLAlchemy model object types.

GrapheneBundle

class flask_unchained.bundles.graphene.GrapheneBundle[source]

The Graphene Bundle. Integrates Flask-GraphQL with SQLAlchemy.

Config

class flask_unchained.bundles.graphene.config.Config[source]
GRAPHENE_URL = '/graphql'

The URL where graphene should be served from. Set to None to disable.

GRAPHENE_BATCH_URL = None

The URL where graphene should be served from in batch mode. Set to None to disable.

GRAPHENE_ENABLE_GRAPHIQL = False

Whether or not to enable GraphIQL.

GRAPHENE_PRETTY_JSON = False

Whether or not to pretty print the returned JSON.

class flask_unchained.bundles.graphene.config.DevConfig[source]
GRAPHENE_ENABLE_GRAPHIQL = True

Whether or not to enable GraphIQL.

GRAPHENE_PRETTY_JSON = True

Whether or not to pretty print the returned JSON.

RegisterGrapheneMutationsHook

class flask_unchained.bundles.graphene.hooks.RegisterGrapheneMutationsHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers Graphene Mutations with the Graphene Bundle.

name: str = 'graphene_mutations'

The name of this hook.

bundle_module_names: Union[List[str], Tuple[str, ...], None] = ['graphene.mutations', 'graphene.schema']

The default module this hook loads from.

Override by setting the graphene_mutations_module_names attribute on your bundle class.

process_objects(app: flask_unchained.flask_unchained.FlaskUnchained, mutations: Dict[str, flask_unchained.bundles.graphene.object_types.MutationsObjectType])[source]

Register discovered mutations with the Graphene Bundle.

type_check(obj: Any)[source]

Returns True if obj is a subclass of MutationsObjectType.

RegisterGrapheneQueriesHook

class flask_unchained.bundles.graphene.hooks.RegisterGrapheneQueriesHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers Graphene Queries with the Graphene Bundle.

name: str = 'graphene_queries'

The name of this hook.

bundle_module_names: Union[List[str], Tuple[str, ...], None] = ['graphene.queries', 'graphene.schema']

The default module this hook loads from.

Override by setting the graphene_queries_module_names attribute on your bundle class.

process_objects(app: flask_unchained.flask_unchained.FlaskUnchained, queries: Dict[str, flask_unchained.bundles.graphene.object_types.QueriesObjectType])[source]

Register discovered queries with the Graphene Bundle.

type_check(obj: Any)[source]

Returns True if obj is a subclass of QueriesObjectType.

RegisterGrapheneRootSchemaHook

class flask_unchained.bundles.graphene.hooks.RegisterGrapheneRootSchemaHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Creates the root graphene.Schema to register with Flask-GraphQL.

name: str = 'graphene_root_schema'

The name of this hook.

run_hook(app: flask_unchained.flask_unchained.FlaskUnchained, bundles: List[flask_unchained.bundles.Bundle], unchained_config: Optional[Dict[str, Any]] = None) → None[source]

Create the root graphene.Schema from queries, mutations, and types discovered by the other hooks and register it with the Graphene Bundle.

RegisterGrapheneTypesHook

class flask_unchained.bundles.graphene.hooks.RegisterGrapheneTypesHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers SQLAlchemyObjectTypes with the Graphene Bundle.

name: str = 'graphene_types'

The name of this hook.

bundle_module_names: Union[List[str], Tuple[str, ...], None] = ['graphene.types', 'graphene.schema']

The default module this hook loads from.

Override by setting the graphene_types_module_names attribute on your bundle class.

process_objects(app: flask_unchained.flask_unchained.FlaskUnchained, types: Dict[str, flask_unchained.bundles.graphene.object_types.SQLAlchemyObjectType])[source]

Implement to do stuff with discovered objects (eg, registering them with the app instance).

type_check(obj: Any)[source]

Implement to determine which objects in a module should be processed by this hook.

QueriesObjectType

class flask_unchained.bundles.graphene.QueriesObjectType(*args, **kwargs)[source]

Base class for query schema definitions. graphene.Field and graphene.List fields are automatically resolved (but you can write your own and it will disable the automatic behavior for that field).

Example usage:

# your_bundle/graphql/schema.py

from flask_unchained.bundles.graphene import QueriesObjectType

from . import types

class YourBundleQueries(QueriesObjectType):
    parent = graphene.Field(types.Parent, id=graphene.ID(required=True))
    parents = graphene.List(types.Parent)

    child = graphene.Field(types.Child, id=graphene.ID(required=True))
    children = graphene.List(types.Child)

    # this is what the default resolvers do, and how you would override them:
    def resolve_child(self, info, **kwargs):
        return types.Child._meta.model.query.get_by(**kwargs)

    def resolve_children(self, info, **kwargs):
        return types.Child._meta.model.query.all()

MutationsObjectType

class flask_unchained.bundles.graphene.MutationsObjectType(*args, **kwargs)[source]

Base class for mutation schema definitions.

Example usage:

#  your_bundle/graphql/mutations.py

import graphene

from flask_unchained import unchained
from flask_unchained.bundles.sqlalchemy import SessionManager, db
from graphql import GraphQLError

from . import types

session_manager: SessionManager = unchained.get_local_proxy('session_manager')

class CreateParent(graphene.Mutation):
    class Arguments:
        name = graphene.String(required=True)
        children = graphene.List(graphene.ID)

    parent = graphene.Field(types.Parent)
    success = graphene.Boolean()

    def mutate(self, info, children, **kwargs):
        if children:
            children = (session_manager
                            .query(types.Child._meta.model)
                            .filter(types.Child._meta.model.id.in_(children))
                            .all())
        try:
            parent = types.Parent._meta.model(children=children, **kwargs)
        except db.ValidationErrors as e:
            raise GraphQLError(str(e))

        session_manager.save(parent, commit=True)
        return CreateParent(parent=parent, success=True)

class DeleteParent(graphene.Mutation):
    class Arguments:
        id = graphene.ID(required=True)

    id = graphene.Int()
    success = graphene.Boolean()

    def mutate(self, info, id):
        parent = session_manager.query(types.Parent._meta.model).get(id)
        session_manager.delete(parent, commit=True)
        return DeleteParent(id=id, success=True)

class EditParent(graphene.Mutation):
    class Arguments:
        id = graphene.ID(required=True)
        name = graphene.String()
        children = graphene.List(graphene.ID)

    parent = graphene.Field(types.Parent)
    success = graphene.Boolean()

    def mutate(self, info, id, children, **kwargs):
        parent = session_manager.query(types.Parent._meta.model).get(id)

        try:
            parent.update(**{k: v for k, v in kwargs.items() if v})
        except db.ValidationErrors as e:
            raise GraphQLError(str(e))

        if children:
            parent.children = (session_manager
                                   .query(types.Child._meta.model)
                                   .filter(types.Child._meta.model.id.in_(children))
                                   .all())

        session_manager.save(parent, commit=True)
        return EditParent(parent=parent, success=True)


# your_bundle/graphql/schema.py

from flask_unchained.bundles.graphene import MutationsObjectType

from . import mutations

class YourBundleMutations(MutationsObjectType):
    create_parent = mutations.CreateParent.Field()
    delete_parent = mutations.DeleteParent.Field()
    edit_parent = mutations.EditParent.Field()

SQLAlchemyObjectType

class flask_unchained.bundles.graphene.SQLAlchemyObjectType(*args, **kwargs)[source]

Base class for SQLAlchemy model object types. Acts exactly the same as graphene_sqlalchemy.SQLAlchemyObjectType, except we’ve added compatibility with the SQLAlchemy Bundle.

Example usage:

# your_bundle/models.py

from flask_unchained.bundles.sqlalchemy import db

class Parent(db.Model):
    name = db.Column(db.String)

    children = db.relationship('Child', back_populates='parent',
                               cascade='all,delete,delete-orphan')

class Child(db.Model):
    name = db.Column(db.String)

    parent_id = db.foreign_key('Parent')
    parent = db.relationship('Parent', back_populates='children')


# your_bundle/graphql/types.py

import graphene

from flask_unchained.bundles.graphene import SQLAlchemyObjectType

from .. import models

class Parent(SQLAlchemyObjectType):
    class Meta:
        model = models.Parent
        only_fields = ('id', 'name', 'created_at', 'updated_at')

    children = graphene.List(lambda: Child)

class Child(SQLAlchemyObjectType):
    class Meta:
        model = models.Child
        only_fields = ('id', 'name', 'created_at', 'updated_at')

    parent = graphene.Field(Parent)