diff --git a/graphene/relay/__init__.py b/graphene/relay/__init__.py index 9e169237..8934ea58 100644 --- a/graphene/relay/__init__.py +++ b/graphene/relay/__init__.py @@ -9,10 +9,11 @@ from .types import ( PageInfo, Edge, Connection, - ClientIDMutation + SimpleConnection, + ClientIDMutation, ) from .utils import is_node __all__ = ['ConnectionField', 'NodeField', 'GlobalIDField', 'Node', - 'PageInfo', 'Edge', 'Connection', 'ClientIDMutation', 'is_node'] + 'PageInfo', 'Edge', 'Connection', 'SimpleConnection', 'ClientIDMutation', 'is_node'] diff --git a/graphene/relay/fields.py b/graphene/relay/fields.py index e79b9592..4b9589d7 100644 --- a/graphene/relay/fields.py +++ b/graphene/relay/fields.py @@ -46,6 +46,10 @@ class ConnectionField(Field): def get_connection_type(self, node): connection_type = self.connection_type or node.get_connection_type() + + if issubclass(connection_type, SimpleConnection): + return connection_type.for_node(node) + edge_type = self.get_edge_type(node) return connection_type.for_node(node, edge_type=edge_type) @@ -54,10 +58,10 @@ class ConnectionField(Field): return edge_type.for_node(node) def get_type(self, schema): - from graphene.relay.utils import is_node + from graphene.relay.utils import is_node, is_node_type type = schema.T(self.type) node = schema.objecttype(type) - assert is_node(node), 'Only nodes have connections.' + assert is_node(node) or is_node_type(node), 'Only nodes have connections.' schema.register(node) connection_type = self.get_connection_type(node) @@ -105,3 +109,5 @@ class GlobalIDField(Field): def resolver(self, instance, args, info): return instance.to_global_id() + +from .types import SimpleConnection diff --git a/graphene/relay/types.py b/graphene/relay/types.py index 3ab55770..a07b8f44 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -49,8 +49,8 @@ class Edge(ObjectType): @classmethod @memoize def for_node(cls, node): - from graphene.relay.utils import is_node - assert is_node(node), 'ObjectTypes in a edge have to be Nodes' + from graphene.relay.utils import is_node, is_node_type + assert is_node(node) or is_node_type(node), 'ObjectTypes in a edge have to be Nodes' node_field = Field(node, description='The item at the end of the edge') return type( '%s%s' % (node._meta.type_name, cls._meta.type_name), @@ -76,15 +76,15 @@ class Connection(ObjectType): @classmethod @memoize - def for_node(cls, node, edge_type=None): - from graphene.relay.utils import is_node + def for_node(cls, node, edge_type=None, root_values=None): + from graphene.relay.utils import is_node, is_node_type edge_type = edge_type or Edge.for_node(node) - assert is_node(node), 'ObjectTypes in a connection have to be Nodes' + assert is_node(node) or is_node_type(node), 'ObjectTypes in a connection have to be Nodes' edges = List(edge_type, description='Information to aid in pagination.') return type( '%s%s' % (node._meta.type_name, cls._meta.type_name), (cls,), - {'edge_type': edge_type, 'edges': edges}) + {'edge_type': edge_type, 'edges': edges, '_root': root_values}) @classmethod def from_list(cls, iterable, args, context, info): @@ -103,6 +103,34 @@ class Connection(ObjectType): return self._connection_data +class SimpleConnection(Connection): + '''A connection without nodes to a list of items.''' + + class Meta: + type_name = 'SimpleConnection' + + @classmethod + @memoize + def for_node(cls, node, root_values=None): + from graphene.relay.utils import is_node, is_node_type + assert is_node(node) or is_node_type(node), 'ObjectTypes in a connection have to be Nodes' + edges = List(node, description='Information to aid in pagination.') + return type( + '%s%s' % (node._meta.type_name, cls._meta.type_name), + (cls,), + {'edge_type': node, 'edges': edges, '_root': root_values}) + + @classmethod + def from_list(cls, iterable, args, context, info): + assert isinstance( + iterable, Iterable), 'Resolved value from the connection field have to be iterable' + connection = connection_from_list( + iterable, args, simple_list=True, connection_type=cls, + edge_type=cls.edge_type, pageinfo_type=PageInfo) + connection.set_connection_data(iterable) + return connection + + class NodeMeta(InterfaceMeta): def construct_get_node(cls):