mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-31 16:07:27 +03:00 
			
		
		
		
	Fixed relay connections/edges field mapping. Improved testing
This commit is contained in:
		
							parent
							
								
									9b635c848c
								
							
						
					
					
						commit
						266dd5efe0
					
				|  | @ -11,7 +11,7 @@ class DjangoConnectionField(ConnectionField): | ||||||
| 
 | 
 | ||||||
|     def wrap_resolved(self, value, instance, args, info): |     def wrap_resolved(self, value, instance, args, info): | ||||||
|         schema = info.schema.graphene_schema |         schema = info.schema.graphene_schema | ||||||
|         return lazy_map(value, self.type.get_object_type(schema)) |         return lazy_map(value, self.type) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class LazyListField(Field): | class LazyListField(Field): | ||||||
|  | @ -22,7 +22,7 @@ class LazyListField(Field): | ||||||
|     def resolver(self, instance, args, info): |     def resolver(self, instance, args, info): | ||||||
|         schema = info.schema.graphene_schema |         schema = info.schema.graphene_schema | ||||||
|         resolved = super(LazyListField, self).resolver(instance, args, info) |         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): | class ConnectionOrListField(Field): | ||||||
|  | @ -30,12 +30,14 @@ class ConnectionOrListField(Field): | ||||||
|     def internal_type(self, schema): |     def internal_type(self, schema): | ||||||
|         model_field = self.type |         model_field = self.type | ||||||
|         field_object_type = model_field.get_object_type(schema) |         field_object_type = model_field.get_object_type(schema) | ||||||
|  |         if not field_object_type: | ||||||
|  |             raise SkipField() | ||||||
|         if is_node(field_object_type): |         if is_node(field_object_type): | ||||||
|             field = DjangoConnectionField(model_field) |             field = DjangoConnectionField(field_object_type) | ||||||
|         else: |         else: | ||||||
|             field = LazyListField(model_field) |             field = LazyListField(field_object_type) | ||||||
|         field.contribute_to_class(self.object_type, self.name) |         field.contribute_to_class(self.object_type, self.name) | ||||||
|         return field.internal_type(schema) |         return schema.T(field) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DjangoModelField(FieldType): | class DjangoModelField(FieldType): | ||||||
|  |  | ||||||
|  | @ -10,12 +10,12 @@ from ..core.types.scalars import ID, Int, String | ||||||
| 
 | 
 | ||||||
| class ConnectionField(Field): | 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): |                  connection_type=None, edge_type=None, **kwargs): | ||||||
|         super( |         super( | ||||||
|             ConnectionField, |             ConnectionField, | ||||||
|             self).__init__( |             self).__init__( | ||||||
|             field_type, |             type, | ||||||
|             resolver=resolver, |             resolver=resolver, | ||||||
|             before=String(), |             before=String(), | ||||||
|             after=String(), |             after=String(), | ||||||
|  | @ -38,7 +38,6 @@ class ConnectionField(Field): | ||||||
|             resolved = self.wrap_resolved(resolved, instance, args, info) |             resolved = self.wrap_resolved(resolved, instance, args, info) | ||||||
|             assert isinstance( |             assert isinstance( | ||||||
|                 resolved, Iterable), 'Resolved value from the connection field have to be iterable' |                 resolved, Iterable), 'Resolved value from the connection field have to be iterable' | ||||||
| 
 |  | ||||||
|             type = schema.T(self.type) |             type = schema.T(self.type) | ||||||
|             node = schema.objecttype(type) |             node = schema.objecttype(type) | ||||||
|             connection_type = self.get_connection_type(node) |             connection_type = self.get_connection_type(node) | ||||||
|  | @ -56,7 +55,8 @@ class ConnectionField(Field): | ||||||
|         return connection_type.for_node(node, edge_type=edge_type) |         return connection_type.for_node(node, edge_type=edge_type) | ||||||
| 
 | 
 | ||||||
|     def get_edge_type(self, node): |     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): |     def get_type(self, schema): | ||||||
|         from graphene.relay.utils import is_node |         from graphene.relay.utils import is_node | ||||||
|  | @ -65,6 +65,7 @@ class ConnectionField(Field): | ||||||
|         assert is_node(node), 'Only nodes have connections.' |         assert is_node(node), 'Only nodes have connections.' | ||||||
|         schema.register(node) |         schema.register(node) | ||||||
|         connection_type = self.get_connection_type(node) |         connection_type = self.get_connection_type(node) | ||||||
|  | 
 | ||||||
|         return connection_type |         return connection_type | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| from pytest import raises | from pytest import raises | ||||||
|  | from graphql.core.type import GraphQLList | ||||||
| 
 | 
 | ||||||
| import graphene | import graphene | ||||||
| from graphene import relay | from graphene import relay | ||||||
|  | @ -31,3 +32,15 @@ def test_node_should_have_same_connection_always(): | ||||||
| 
 | 
 | ||||||
| def test_node_should_have_id_field(): | def test_node_should_have_id_field(): | ||||||
|     assert 'id' in OtherNode._meta.fields_map |     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) | ||||||
|  |  | ||||||
|  | @ -24,11 +24,6 @@ class PageInfo(ObjectType): | ||||||
| 
 | 
 | ||||||
| class Edge(ObjectType): | class Edge(ObjectType): | ||||||
|     '''An edge in a connection.''' |     '''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( |     cursor = String( | ||||||
|         required=True, description='A cursor for use in pagination') |         required=True, description='A cursor for use in pagination') | ||||||
| 
 | 
 | ||||||
|  | @ -37,10 +32,11 @@ class Edge(ObjectType): | ||||||
|     def for_node(cls, node): |     def for_node(cls, node): | ||||||
|         from graphene.relay.utils import is_node |         from graphene.relay.utils import is_node | ||||||
|         assert is_node(node), 'ObjectTypes in a edge have to be Nodes' |         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( |         return type( | ||||||
|             '%s%s' % (node._meta.type_name, cls._meta.type_name), |             '%s%s' % (node._meta.type_name, cls._meta.type_name), | ||||||
|             (cls,), |             (cls,), | ||||||
|             {'node_type': node}) |             {'node_type': node, 'node': node_field}) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Connection(ObjectType): | class Connection(ObjectType): | ||||||
|  | @ -50,8 +46,6 @@ class Connection(ObjectType): | ||||||
| 
 | 
 | ||||||
|     page_info = Field(PageInfo, required=True, |     page_info = Field(PageInfo, required=True, | ||||||
|                       description='The Information to aid in pagination') |                       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 |     _connection_data = None | ||||||
| 
 | 
 | ||||||
|  | @ -59,12 +53,13 @@ class Connection(ObjectType): | ||||||
|     @memoize |     @memoize | ||||||
|     def for_node(cls, node, edge_type=None): |     def for_node(cls, node, edge_type=None): | ||||||
|         from graphene.relay.utils import is_node |         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' |         assert is_node(node), 'ObjectTypes in a connection have to be Nodes' | ||||||
|  |         edges = List(edge_type, description='Information to aid in pagination.') | ||||||
|         return type( |         return type( | ||||||
|             '%s%s' % (node._meta.type_name, cls._meta.type_name), |             '%s%s' % (node._meta.type_name, cls._meta.type_name), | ||||||
|             (cls,), |             (cls,), | ||||||
|             {'edge_type': edge_type.for_node(node)}) |             {'edge_type': edge_type, 'edges': edges}) | ||||||
| 
 | 
 | ||||||
|     def set_connection_data(self, data): |     def set_connection_data(self, data): | ||||||
|         self._connection_data = data |         self._connection_data = data | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user