Skip to content

Commit

Permalink
Fixed relay connections/edges field mapping. Improved testing
Browse files Browse the repository at this point in the history
  • Loading branch information
syrusakbary committed Nov 18, 2015
1 parent 9b635c8 commit 266dd5e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 19 deletions.
12 changes: 7 additions & 5 deletions graphene/contrib/django/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DjangoConnectionField(ConnectionField):

def wrap_resolved(self, value, instance, args, info):
schema = info.schema.graphene_schema
return lazy_map(value, self.type.get_object_type(schema))
return lazy_map(value, self.type)


class LazyListField(Field):
Expand All @@ -22,20 +22,22 @@ def get_type(self, schema):
def resolver(self, instance, args, info):
schema = info.schema.graphene_schema
resolved = super(LazyListField, self).resolver(instance, args, info)
return lazy_map(resolved, self.get_object_type(schema))
return lazy_map(resolved, self.type)


class ConnectionOrListField(Field):

def internal_type(self, schema):
model_field = self.type
field_object_type = model_field.get_object_type(schema)
if not field_object_type:
raise SkipField()
if is_node(field_object_type):
field = DjangoConnectionField(model_field)
field = DjangoConnectionField(field_object_type)
else:
field = LazyListField(model_field)
field = LazyListField(field_object_type)
field.contribute_to_class(self.object_type, self.name)
return field.internal_type(schema)
return schema.T(field)


class DjangoModelField(FieldType):
Expand Down
9 changes: 5 additions & 4 deletions graphene/relay/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@

class ConnectionField(Field):

def __init__(self, field_type, resolver=None, description='',
def __init__(self, type, resolver=None, description='',
connection_type=None, edge_type=None, **kwargs):
super(
ConnectionField,
self).__init__(
field_type,
type,
resolver=resolver,
before=String(),
after=String(),
Expand All @@ -38,7 +38,6 @@ def resolver(self, instance, args, info):
resolved = self.wrap_resolved(resolved, instance, args, info)
assert isinstance(
resolved, Iterable), 'Resolved value from the connection field have to be iterable'

type = schema.T(self.type)
node = schema.objecttype(type)
connection_type = self.get_connection_type(node)
Expand All @@ -56,7 +55,8 @@ def get_connection_type(self, node):
return connection_type.for_node(node, edge_type=edge_type)

def get_edge_type(self, node):
return self.edge_type or node.get_edge_type()
edge_type = self.edge_type or node.get_edge_type()
return edge_type.for_node(node)

def get_type(self, schema):
from graphene.relay.utils import is_node
Expand All @@ -65,6 +65,7 @@ def get_type(self, schema):
assert is_node(node), 'Only nodes have connections.'
schema.register(node)
connection_type = self.get_connection_type(node)

return connection_type


Expand Down
13 changes: 13 additions & 0 deletions graphene/relay/tests/test_types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pytest import raises
from graphql.core.type import GraphQLList

import graphene
from graphene import relay
Expand Down Expand Up @@ -31,3 +32,15 @@ def test_node_should_have_same_connection_always():

def test_node_should_have_id_field():
assert 'id' in OtherNode._meta.fields_map


def test_node_connection_should_have_edge():
connection = relay.Connection.for_node(OtherNode)
edge = relay.Edge.for_node(OtherNode)
connection_type = schema.T(connection)
connection_fields = connection_type.get_fields()
assert 'edges' in connection_fields
assert 'pageInfo' in connection_fields
edges_type = connection_fields['edges'].type
assert isinstance(edges_type, GraphQLList)
assert edges_type.of_type == schema.T(edge)
15 changes: 5 additions & 10 deletions graphene/relay/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ class PageInfo(ObjectType):

class Edge(ObjectType):
'''An edge in a connection.'''
class Meta:
type_name = 'DefaultEdge'

node = Field(LazyType(lambda object_type: object_type.node_type),
description='The item at the end of the edge')
cursor = String(
required=True, description='A cursor for use in pagination')

Expand All @@ -37,10 +32,11 @@ class Meta:
def for_node(cls, node):
from graphene.relay.utils import is_node
assert is_node(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),
(cls,),
{'node_type': node})
{'node_type': node, 'node': node_field})


class Connection(ObjectType):
Expand All @@ -50,21 +46,20 @@ class Meta:

page_info = Field(PageInfo, required=True,
description='The Information to aid in pagination')
edges = List(LazyType(lambda object_type: object_type.edge_type),
description='Information to aid in pagination.')

_connection_data = None

@classmethod
@memoize
def for_node(cls, node, edge_type=None):
from graphene.relay.utils import is_node
edge_type = edge_type or Edge
edge_type = edge_type or Edge.for_node(node)
assert is_node(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.for_node(node)})
{'edge_type': edge_type, 'edges': edges})

def set_connection_data(self, data):
self._connection_data = data
Expand Down

0 comments on commit 266dd5e

Please sign in to comment.