mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-30 23:47:55 +03:00 
			
		
		
		
	Used Graphene types for relay Connection and Edges
This commit is contained in:
		
							parent
							
								
									752cd77652
								
							
						
					
					
						commit
						84fcb3eac9
					
				|  | @ -30,7 +30,7 @@ class ObjectTypeMeta(type): | ||||||
|             # If this isn't a subclass of Model, don't do anything special. |             # If this isn't a subclass of Model, don't do anything special. | ||||||
|             return super_new(cls, name, bases, attrs) |             return super_new(cls, name, bases, attrs) | ||||||
| 
 | 
 | ||||||
|         module = attrs.pop('__module__') |         module = attrs.pop('__module__', None) | ||||||
|         doc = attrs.pop('__doc__', None) |         doc = attrs.pop('__doc__', None) | ||||||
|         new_class = super_new(cls, name, bases, { |         new_class = super_new(cls, name, bases, { | ||||||
|             '__module__': module, |             '__module__': module, | ||||||
|  |  | ||||||
|  | @ -4,6 +4,11 @@ from graphene.relay.fields import ( | ||||||
|     GlobalIDField, |     GlobalIDField, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| from graphene.relay.types import Node | from graphene.relay.types import ( | ||||||
|  | 	Node, | ||||||
|  | 	PageInfo, | ||||||
|  | 	Edge, | ||||||
|  | 	Connection | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| from graphene.relay.utils import is_node | from graphene.relay.utils import is_node | ||||||
|  |  | ||||||
|  | @ -21,9 +21,14 @@ from graphene.utils import memoize | ||||||
| 
 | 
 | ||||||
| class ConnectionField(Field): | class ConnectionField(Field): | ||||||
| 
 | 
 | ||||||
|     def __init__(self, field_type, resolve=None, description=''): |     def __init__(self, field_type, resolve=None, description='', connection_type=None, edge_type=None, **kwargs): | ||||||
|  |         from graphene.relay.types import Connection, Edge | ||||||
|         super(ConnectionField, self).__init__(field_type, resolve=resolve, |         super(ConnectionField, self).__init__(field_type, resolve=resolve, | ||||||
|                                               args=connectionArgs, description=description) |                                               args=connectionArgs, description=description, **kwargs) | ||||||
|  |         self.connection_type = connection_type or Connection | ||||||
|  |         self.edge_type = edge_type or Edge | ||||||
|  |         assert issubclass(self.connection_type, Connection), 'connection_type in %r must be a subclass of Connection' % self | ||||||
|  |         assert issubclass(self.edge_type, Edge), 'edge_type in %r must be a subclass of Edge' % self | ||||||
| 
 | 
 | ||||||
|     def wrap_resolved(self, value, instance, args, info): |     def wrap_resolved(self, value, instance, args, info): | ||||||
|         return value |         return value | ||||||
|  | @ -39,9 +44,12 @@ class ConnectionField(Field): | ||||||
|     @memoize |     @memoize | ||||||
|     def internal_type(self, schema): |     def internal_type(self, schema): | ||||||
|         from graphene.relay.utils import is_node |         from graphene.relay.utils import is_node | ||||||
|         object_type = self.get_object_type(schema) |         node = self.get_object_type(schema) | ||||||
|         assert is_node(object_type), 'Only nodes have connections.' |         assert is_node(node), 'Only nodes have connections.' | ||||||
|         return object_type.get_connection(schema) |         schema.register(node) | ||||||
|  |         edge_node_type = self.edge_type.for_node(node) | ||||||
|  |         connection_node_type = self.connection_type.for_node(node, edge_type=edge_node_type) | ||||||
|  |         return connection_node_type.internal_type(schema) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NodeField(Field): | class NodeField(Field): | ||||||
|  |  | ||||||
|  | @ -5,7 +5,8 @@ from graphql_relay.connection.connection import ( | ||||||
|     connection_definitions |     connection_definitions | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| from graphene.core.types import Interface | from graphene.core.types import Interface, ObjectType | ||||||
|  | from graphene.core.fields import BooleanField, StringField, ListField, Field | ||||||
| from graphene.relay.fields import GlobalIDField | from graphene.relay.fields import GlobalIDField | ||||||
| from graphene.utils import memoize | from graphene.utils import memoize | ||||||
| 
 | 
 | ||||||
|  | @ -35,3 +36,37 @@ class BaseNode(object): | ||||||
| class Node(BaseNode, Interface): | class Node(BaseNode, Interface): | ||||||
|     '''An object with an ID''' |     '''An object with an ID''' | ||||||
|     id = GlobalIDField() |     id = GlobalIDField() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PageInfo(ObjectType): | ||||||
|  |     has_next_page = BooleanField(required=True, description='When paginating forwards, are there more items?') | ||||||
|  |     has_previous_page = BooleanField(required=True, description='When paginating backwards, are there more items?') | ||||||
|  |     start_cursor = StringField(description='When paginating backwards, the cursor to continue.') | ||||||
|  |     end_cursor = StringField(description='When paginating forwards, the cursor to continue.') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Edge(ObjectType): | ||||||
|  |     '''An edge in a connection.''' | ||||||
|  |     node = Field(lambda field: field.object_type.node_type, description='The item at the end of the edge') | ||||||
|  |     end_cursor = StringField(required=True, description='A cursor for use in pagination') | ||||||
|  | 
 | ||||||
|  |     @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' | ||||||
|  |         return type('%sEdge' % node._meta.type_name, (cls, ), {'node_type': node}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Connection(ObjectType): | ||||||
|  |     '''A connection to a list of items.''' | ||||||
|  |     page_info = Field(PageInfo, required=True, description='The Information to aid in pagination') | ||||||
|  |     edges = ListField(lambda field: field.object_type.edge_type, description='Information to aid in pagination.') | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     @memoize | ||||||
|  |     def for_node(cls, node, edge_type=None): | ||||||
|  |         from graphene.relay.utils import is_node | ||||||
|  |         edge_type = edge_type or Edge | ||||||
|  |         assert is_node(node), 'ObjectTypes in a connection have to be Nodes' | ||||||
|  |         return type('%sConnection' % node._meta.type_name, (cls, ), {'edge_type': edge_type.for_node(node)}) | ||||||
|  |  | ||||||
|  | @ -12,6 +12,11 @@ schema = graphene.Schema() | ||||||
| 
 | 
 | ||||||
| class MyType(object): | class MyType(object): | ||||||
|     name = 'my' |     name = 'my' | ||||||
|  |     arg = None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MyConnection(relay.Connection): | ||||||
|  |     my_custom_field = graphene.StringField(resolve=lambda instance, *_: 'Custom') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MyNode(relay.Node): | class MyNode(relay.Node): | ||||||
|  | @ -24,7 +29,13 @@ class MyNode(relay.Node): | ||||||
| 
 | 
 | ||||||
| class Query(graphene.ObjectType): | class Query(graphene.ObjectType): | ||||||
|     my_node = relay.NodeField(MyNode) |     my_node = relay.NodeField(MyNode) | ||||||
|  |     all_my_nodes = relay.ConnectionField(MyNode, connection_type=MyConnection, customArg=graphene.Argument(graphene.String)) | ||||||
| 
 | 
 | ||||||
|  |     def resolve_all_my_nodes(self, args, info): | ||||||
|  |         t = MyType() | ||||||
|  |         custom_arg = args.get('customArg') | ||||||
|  |         assert custom_arg == "1" | ||||||
|  |         return [MyNode(t)] | ||||||
| 
 | 
 | ||||||
| schema.query = Query | schema.query = Query | ||||||
| 
 | 
 | ||||||
|  | @ -34,12 +45,34 @@ def test_nodefield_query(): | ||||||
|     query RebelsShipsQuery { |     query RebelsShipsQuery { | ||||||
|       myNode(id:"TXlOb2RlOjE=") { |       myNode(id:"TXlOb2RlOjE=") { | ||||||
|         name |         name | ||||||
|  |       }, | ||||||
|  |       allMyNodes (customArg:"1") { | ||||||
|  |         edges { | ||||||
|  |           node { | ||||||
|  |             name | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         myCustomField | ||||||
|  |         pageInfo { | ||||||
|  |           hasNextPage | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     ''' |     ''' | ||||||
|     expected = { |     expected = { | ||||||
|         'myNode': { |         'myNode': { | ||||||
|             'name': 'my' |             'name': 'my' | ||||||
|  |         }, | ||||||
|  |         'allMyNodes': { | ||||||
|  |             'edges': [{ | ||||||
|  |                 'node': { | ||||||
|  |                     'name': 'my' | ||||||
|  |                 } | ||||||
|  |             }], | ||||||
|  |             'myCustomField': 'Custom', | ||||||
|  |             'pageInfo': { | ||||||
|  |                 'hasNextPage': False, | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     result = schema.execute(query) |     result = schema.execute(query) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user