diff --git a/graphene_django/__init__.py b/graphene_django/__init__.py index 5401565..050e083 100644 --- a/graphene_django/__init__.py +++ b/graphene_django/__init__.py @@ -1,6 +1,6 @@ from .types import DjangoObjectType from .fields import DjangoConnectionField -__version__ = "2.2.2" +__version__ = "2.2.3" __all__ = ["__version__", "DjangoObjectType", "DjangoConnectionField"] diff --git a/graphene_django/relationship/edges.py b/graphene_django/relationship/edges.py index 7395971..d9e14ea 100644 --- a/graphene_django/relationship/edges.py +++ b/graphene_django/relationship/edges.py @@ -1,14 +1,18 @@ from functools import singledispatch from typing import Union, Callable, Optional, Type +from types import GeneratorType +from functools import wraps, single_dispatch from django.utils.translation import ugettext as _ from graphene import String, List, ID, ObjectType, Field from graphene.types.mountedtype import MountedType from graphene.types.unmountedtype import UnmountedType from graphene_django.types import DjangoObjectType -from neomodel.core import StructuredNode +from neomodel import ( + StructuredNode, + NodeSet, +) -from graphene_ql.decorators import paginate from .lib import ( GrapheneQLEdgeException, @@ -17,6 +21,58 @@ from .lib import ( ) +@singledispatch +def paginate_instance(qs, kwargs): + """ Paginate difference of type qs. + If list or tuple just primitive slicing + If + """ + raise NotImplementedError("Type {} not implemented yet.".format(type(qs))) + + +def paginate(resolver): + """ Paginator for resolver functions + Input types: + list, tuple, NodeSet + """ + @wraps(resolver) + def wrapper(root, info, **kwargs): + qs = resolver(root, info, **kwargs) + qs = paginate_instance(qs, kwargs) + return qs + return wrapper + + +@paginate_instance.register(NodeSet) +def paginate_nodeset(qs, kwargs): + # Warning. Type of pagination is lazy + if 'first' in kwargs and 'last' in kwargs: + qs = qs.set_skip(kwargs['first'] - kwargs['last']) + qs = qs.set_limit(kwargs['last']) + elif 'last' in kwargs: + count = len(qs) + qs = qs.set_skip(count - kwargs['last']) + qs = qs.set_limit(kwargs['last']) + elif 'first' in kwargs: + qs = qs.set_limit(kwargs['first']) + return qs + + +@paginate_instance.register(list) +@paginate_instance.register(tuple) +@paginate_instance.register(GeneratorType) +def paginate_list(qs, kwargs): + if 'first' in kwargs and 'last' in kwargs: + qs = qs[:kwargs['first']] + qs = qs[kwargs['last']:] + elif 'first' in kwargs: + qs = qs[:kwargs['first']] + elif 'last' in kwargs: + qs = qs[-kwargs['last']:] + return qs + + + def EdgeNode(*args, **kwargs): """ Edge between nodes Attrs: