Skip to content

Commit a7cf71f

Browse files
committed
Merge pull request #44 from graphql-python/relay-connections
Relay connections
2 parents b1e0c3b + c28b046 commit a7cf71f

File tree

11 files changed

+50
-111
lines changed

11 files changed

+50
-111
lines changed

graphene/contrib/django/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from graphene.contrib.django.types import (
2+
DjangoConnection,
23
DjangoObjectType,
34
DjangoInterface,
45
DjangoNode
@@ -9,4 +10,4 @@
910
)
1011

1112
__all__ = ['DjangoObjectType', 'DjangoInterface', 'DjangoNode',
12-
'DjangoConnectionField', 'DjangoModelField']
13+
'DjangoConnection', 'DjangoConnectionField', 'DjangoModelField']

graphene/contrib/django/fields.py

+10-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
1+
import warnings
2+
13
from ...core.exceptions import SkipField
24
from ...core.fields import Field
35
from ...core.types.base import FieldType
46
from ...core.types.definitions import List
57
from ...relay import ConnectionField
68
from ...relay.utils import is_node
7-
from .utils import get_type_for_model, lazy_map
9+
from .utils import get_type_for_model
810

911

1012
class DjangoConnectionField(ConnectionField):
1113

12-
def wrap_resolved(self, value, instance, args, info):
13-
return lazy_map(value, self.type)
14-
15-
16-
class LazyListField(Field):
17-
18-
def get_type(self, schema):
19-
return List(self.type)
20-
21-
def resolver(self, instance, args, info):
22-
resolved = super(LazyListField, self).resolver(instance, args, info)
23-
return lazy_map(resolved, self.type)
14+
def __init__(self, *args, **kwargs):
15+
cls = self.__class__
16+
warnings.warn("Using {} will be not longer supported."
17+
" Use relay.ConnectionField instead".format(cls.__name__),
18+
FutureWarning)
19+
return super(DjangoConnectionField, self).__init__(*args, **kwargs)
2420

2521

2622
class ConnectionOrListField(Field):
@@ -33,7 +29,7 @@ def internal_type(self, schema):
3329
if is_node(field_object_type):
3430
field = DjangoConnectionField(field_object_type)
3531
else:
36-
field = LazyListField(field_object_type)
32+
field = Field(List(field_object_type))
3733
field.contribute_to_class(self.object_type, self.attname)
3834
return schema.T(field)
3935

graphene/contrib/django/types.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
from ...core.types import BaseObjectType, ObjectTypeMeta
44
from ...relay.fields import GlobalIDField
5-
from ...relay.types import BaseNode
5+
from ...relay.types import BaseNode, Connection
66
from .converter import convert_django_field
77
from .options import DjangoOptions
8-
from .utils import get_reverse_fields
8+
from .utils import get_reverse_fields, maybe_queryset
99

1010

1111
class DjangoObjectTypeMeta(ObjectTypeMeta):
@@ -30,7 +30,7 @@ def add_extra_fields(cls):
3030
is_excluded = field.name in cls._meta.exclude_fields or is_already_created
3131
if is_not_in_only or is_excluded:
3232
# We skip this field if we specify only_fields and is not
33-
# in there. Or when we excldue this field in exclude_fields
33+
# in there. Or when we exclude this field in exclude_fields
3434
continue
3535
converted_field = convert_django_field(field)
3636
cls.add_to_class(field.name, converted_field)
@@ -71,6 +71,14 @@ class DjangoInterface(six.with_metaclass(
7171
pass
7272

7373

74+
class DjangoConnection(Connection):
75+
76+
@classmethod
77+
def from_list(cls, iterable, *args, **kwargs):
78+
iterable = maybe_queryset(iterable)
79+
return super(DjangoConnection, cls).from_list(iterable, *args, **kwargs)
80+
81+
7482
class DjangoNode(BaseNode, DjangoInterface):
7583
id = GlobalIDField()
7684

@@ -81,3 +89,5 @@ def get_node(cls, id, info=None):
8189
return cls(instance)
8290
except cls._meta.model.DoesNotExist:
8391
return None
92+
93+
connection_type = DjangoConnection

graphene/contrib/django/utils.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
from django.db import models
22
from django.db.models.manager import Manager
3-
from django.db.models.query import QuerySet
4-
5-
from ...utils import LazyMap
63

74

85
def get_type_for_model(schema, model):
@@ -22,9 +19,7 @@ def get_reverse_fields(model):
2219
yield related
2320

2421

25-
def lazy_map(value, func):
22+
def maybe_queryset(value):
2623
if isinstance(value, Manager):
2724
value = value.get_queryset()
28-
if isinstance(value, QuerySet):
29-
return LazyMap(value, func)
3025
return value

graphene/core/types/objecttype.py

+4
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ def get_fields(cls, schema):
219219

220220
return OrderedDict(fields)
221221

222+
@classmethod
223+
def wrap(cls, instance, args, info):
224+
return cls(_root=instance)
225+
222226

223227
class Interface(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
224228
pass

graphene/relay/fields.py

+3-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
from collections import Iterable
2-
3-
from graphql_relay.connection.arrayconnection import connection_from_list
41
from graphql_relay.node.node import from_global_id
52

63
from ..core.fields import Field
@@ -30,24 +27,11 @@ def wrap_resolved(self, value, instance, args, info):
3027
return value
3128

3229
def resolver(self, instance, args, info):
33-
from graphene.relay.types import PageInfo
3430
schema = info.schema.graphene_schema
35-
31+
connection_type = self.get_type(schema)
3632
resolved = super(ConnectionField, self).resolver(instance, args, info)
37-
if resolved:
38-
resolved = self.wrap_resolved(resolved, instance, args, info)
39-
assert isinstance(
40-
resolved, Iterable), 'Resolved value from the connection field have to be iterable'
41-
type = schema.T(self.type)
42-
node = schema.objecttype(type)
43-
connection_type = self.get_connection_type(node)
44-
edge_type = self.get_edge_type(node)
45-
46-
connection = connection_from_list(
47-
resolved, args, connection_type=connection_type,
48-
edge_type=edge_type, pageinfo_type=PageInfo)
49-
connection.set_connection_data(resolved)
50-
return connection
33+
if not isinstance(resolved, connection_type):
34+
return connection_type.from_list(resolved, args, info)
5135

5236
def get_connection_type(self, node):
5337
connection_type = self.connection_type or node.get_connection_type()

graphene/relay/types.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import inspect
22
import warnings
3+
from collections import Iterable
34
from functools import wraps
5+
6+
from graphql_relay.connection.arrayconnection import connection_from_list
47
from graphql_relay.node.node import to_global_id
58

69
from ..core.types import (Boolean, Field, InputObjectType, Interface, List,
@@ -63,6 +66,16 @@ def for_node(cls, node, edge_type=None):
6366
(cls,),
6467
{'edge_type': edge_type, 'edges': edges})
6568

69+
@classmethod
70+
def from_list(cls, iterable, args, info):
71+
assert isinstance(
72+
iterable, Iterable), 'Resolved value from the connection field have to be iterable'
73+
connection = connection_from_list(
74+
iterable, args, connection_type=cls,
75+
edge_type=cls.edge_type, pageinfo_type=PageInfo)
76+
connection.set_connection_data(iterable)
77+
return connection
78+
6679
def set_connection_data(self, data):
6780
self._connection_data = data
6881

graphene/utils/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
from .str_converters import to_camel_case, to_snake_case
22
from .proxy_snake_dict import ProxySnakeDict
33
from .caching import cached_property, memoize
4-
from .lazymap import LazyMap
54
from .misc import enum_to_graphql_enum
65
from .resolve_only_args import resolve_only_args
76

87

98
__all__ = ['to_camel_case', 'to_snake_case', 'ProxySnakeDict',
10-
'cached_property', 'memoize', 'LazyMap', 'enum_to_graphql_enum',
9+
'cached_property', 'memoize', 'enum_to_graphql_enum',
1110
'resolve_only_args']

graphene/utils/lazymap.py

-43
This file was deleted.

graphene/utils/tests/test_lazymap.py

-23
This file was deleted.

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ max-line-length = 120
44

55
[coverage:run]
66
omit = core/ntypes/tests/*
7+
8+
[isort]
9+
known_first_party=graphene

0 commit comments

Comments
 (0)