Skip to content

Commit 3ae05e0

Browse files
authored
Merge pull request #22 from alqmy/master
feat: Added before and after and maybe fixed last pagination issue.
2 parents 5aca93e + 9b0ed7f commit 3ae05e0

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

graphene_mongo/fields.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
class MongoengineListField(Field):
1616

1717
def __init__(self, _type, *args, **kwargs):
18-
super(MongoengineListField, self).__init__(List(_type), *args, **kwargs)
18+
super(MongoengineListField, self).__init__(
19+
List(_type), *args, **kwargs)
1920

2021
@property
2122
def model(self):
@@ -42,8 +43,10 @@ def __init__(self, type, *args, **kwargs):
4243
def type(self):
4344
from .types import MongoengineObjectType
4445
_type = super(ConnectionField, self).type
45-
assert issubclass(_type, MongoengineObjectType), "MongoengineConnectionField only accepts MongoengineObjectType types"
46-
assert _type._meta.connection, "The type {} doesn't have a connection".format(_type.__name__)
46+
assert issubclass(
47+
_type, MongoengineObjectType), "MongoengineConnectionField only accepts MongoengineObjectType types"
48+
assert _type._meta.connection, "The type {} doesn't have a connection".format(
49+
_type.__name__)
4750
return _type._meta.connection
4851

4952
@property
@@ -68,10 +71,11 @@ def args(self, args):
6871
def default_filter_args(self):
6972
def is_filterable(kv):
7073
return hasattr(kv[1], '_type') \
71-
and callable(getattr(kv[1]._type, '_of_type', None))
74+
and callable(getattr(kv[1]._type, '_of_type', None))
7275

7376
return reduce(
74-
lambda r, kv: r.update({kv[0]: kv[1]._type._of_type()}) or r if is_filterable(kv) else r,
77+
lambda r, kv: r.update(
78+
{kv[0]: kv[1]._type._of_type()}) or r if is_filterable(kv) else r,
7579
self.fields.items(),
7680
{}
7781
)
@@ -96,17 +100,29 @@ def get_query(cls, model, info, **args):
96100
first = args.pop('first', None)
97101
last = args.pop('last', None)
98102
id = args.pop('id', None)
103+
before = args.pop('before', None)
104+
after = args.pop('after', None)
99105

100106
if id is not None:
101107
# https://github.com/graphql-python/graphene/issues/124
102108
args['pk'] = from_global_id(id)[-1]
103109

104110
objs = objs.filter(**args)
105111

112+
# https://github.com/graphql-python/graphene-mongo/issues/21
113+
if after is not None:
114+
_after = int(from_global_id(after)[-1])
115+
objs = objs[_after:]
116+
117+
if before is not None:
118+
_before = int(from_global_id(before)[-1])
119+
objs = objs[:_before]
120+
106121
if first is not None:
107122
objs = objs[:first]
108123
if last is not None:
109-
objs = objs[:-last]
124+
# fix for https://github.com/graphql-python/graphene-mongo/issues/20
125+
objs = objs[-last:]
110126

111127
return objs
112128

graphene_mongo/tests/test_relay_query.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,89 @@ class Query(graphene.ObjectType):
364364
assert all(item in get_nodes(result.data, 'editors') for item in get_nodes(expected, 'editors'))
365365

366366

367+
def test_should_after():
368+
class Query(graphene.ObjectType):
369+
370+
players = MongoengineConnectionField(PlayerNode)
371+
372+
query = '''
373+
query EditorQuery {
374+
players(after: "YXJyYXljb25uZWN0aW9uOjA=") {
375+
edges {
376+
cursor,
377+
node {
378+
firstName
379+
}
380+
}
381+
}
382+
}
383+
'''
384+
expected = {
385+
'players': {
386+
'edges': [
387+
{
388+
'cursor': 'YXJyYXljb25uZWN0aW9uOjE=',
389+
'node': {
390+
'firstName': 'Magic',
391+
}
392+
},
393+
{
394+
'cursor': 'YXJyYXljb25uZWN0aW9uOjI=',
395+
'node': {
396+
'firstName': 'Larry'
397+
}
398+
}
399+
]
400+
}
401+
}
402+
schema = graphene.Schema(query=Query)
403+
result = schema.execute(query)
404+
405+
assert not result.errors
406+
assert json.dumps(result.data, sort_keys=True) == json.dumps(expected, sort_keys=True)
407+
408+
409+
def test_should_before():
410+
class Query(graphene.ObjectType):
411+
412+
players = MongoengineConnectionField(PlayerNode)
413+
414+
query = '''
415+
query EditorQuery {
416+
players(before: "YXJyYXljb25uZWN0aW9uOjI=") {
417+
edges {
418+
cursor,
419+
node {
420+
firstName
421+
}
422+
}
423+
}
424+
}
425+
'''
426+
expected = {
427+
'players': {
428+
'edges': [
429+
{
430+
'cursor': "YXJyYXljb25uZWN0aW9uOjA=",
431+
'node': {
432+
'firstName': 'Michael',
433+
}
434+
},
435+
{
436+
'cursor': 'YXJyYXljb25uZWN0aW9uOjE=',
437+
'node': {
438+
'firstName': 'Magic',
439+
}
440+
}
441+
]
442+
}
443+
}
444+
schema = graphene.Schema(query=Query)
445+
result = schema.execute(query)
446+
447+
assert not result.errors
448+
assert json.dumps(result.data, sort_keys=True) == json.dumps(expected, sort_keys=True)
449+
367450
def test_should_self_reference():
368451

369452
class Query(graphene.ObjectType):
@@ -463,6 +546,7 @@ class Query(graphene.ObjectType):
463546
assert not result.errors
464547
assert json.dumps(result.data, sort_keys=True) == json.dumps(expected, sort_keys=True)
465548

549+
466550
# TODO:
467551
def test_should_paging():
468552
pass

0 commit comments

Comments
 (0)