mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 12:44:15 +03:00
Added LazyMap for django resolvers
This commit is contained in:
parent
1eee2912d8
commit
52cb1715d3
|
@ -4,7 +4,7 @@ from graphene.core.fields import (
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
|
||||||
from graphene.core.fields import Field, LazyField
|
from graphene.core.fields import Field, LazyField
|
||||||
from graphene.utils import cached_property, memoize
|
from graphene.utils import cached_property, memoize, LazyMap
|
||||||
|
|
||||||
from graphene.relay.types import BaseNode
|
from graphene.relay.types import BaseNode
|
||||||
|
|
||||||
|
@ -22,17 +22,26 @@ def get_type_for_model(schema, model):
|
||||||
return _type
|
return _type
|
||||||
|
|
||||||
|
|
||||||
class DjangoConnectionField(relay.ConnectionField):
|
def lazy_map(value, func):
|
||||||
|
if isinstance(value, Manager):
|
||||||
|
value = value.get_queryset()
|
||||||
|
if isinstance(value, QuerySet):
|
||||||
|
return LazyMap(value, func)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class DjangoConnectionField(relay.ConnectionField):
|
||||||
def wrap_resolved(self, value, instance, args, info):
|
def wrap_resolved(self, value, instance, args, info):
|
||||||
if isinstance(value, (QuerySet, Manager)):
|
return lazy_map(value, instance.__class__)
|
||||||
cls = instance.__class__
|
|
||||||
value = [cls(s) for s in value.all()]
|
|
||||||
return value
|
class LazyListField(ListField):
|
||||||
|
def resolve(self, value, instance, args, info):
|
||||||
|
resolved = super(LazyListField, self).resolve(value, instance, args, info)
|
||||||
|
return lazy_map(resolved, instance.__class__)
|
||||||
|
|
||||||
|
|
||||||
class ConnectionOrListField(LazyField):
|
class ConnectionOrListField(LazyField):
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def get_field(self, schema):
|
def get_field(self, schema):
|
||||||
model_field = self.field_type
|
model_field = self.field_type
|
||||||
|
@ -40,13 +49,12 @@ class ConnectionOrListField(LazyField):
|
||||||
if field_object_type and issubclass(field_object_type, BaseNode):
|
if field_object_type and issubclass(field_object_type, BaseNode):
|
||||||
field = DjangoConnectionField(model_field)
|
field = DjangoConnectionField(model_field)
|
||||||
else:
|
else:
|
||||||
field = ListField(model_field)
|
field = LazyListField(model_field)
|
||||||
field.contribute_to_class(self.object_type, self.name)
|
field.contribute_to_class(self.object_type, self.name)
|
||||||
return field
|
return field
|
||||||
|
|
||||||
|
|
||||||
class DjangoModelField(Field):
|
class DjangoModelField(Field):
|
||||||
|
|
||||||
def __init__(self, model, *args, **kwargs):
|
def __init__(self, model, *args, **kwargs):
|
||||||
super(DjangoModelField, self).__init__(None, *args, **kwargs)
|
super(DjangoModelField, self).__init__(None, *args, **kwargs)
|
||||||
self.model = model
|
self.model = model
|
||||||
|
|
|
@ -101,6 +101,8 @@ class BaseObjectType(object):
|
||||||
raise Exception("An interface cannot be initialized")
|
raise Exception("An interface cannot be initialized")
|
||||||
if instance is None:
|
if instance is None:
|
||||||
return None
|
return None
|
||||||
|
elif type(instance) is cls:
|
||||||
|
instance = instance.instance
|
||||||
return super(BaseObjectType, cls).__new__(cls, instance, *args, **kwargs)
|
return super(BaseObjectType, cls).__new__(cls, instance, *args, **kwargs)
|
||||||
|
|
||||||
def __init__(self, instance=None):
|
def __init__(self, instance=None):
|
||||||
|
@ -115,9 +117,12 @@ class BaseObjectType(object):
|
||||||
def get_field(self, field):
|
def get_field(self, field):
|
||||||
return getattr(self.instance, field, None)
|
return getattr(self.instance, field, None)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.instance.__eq__(other)
|
||||||
|
|
||||||
def resolve(self, field_name, args, info):
|
def resolve(self, field_name, args, info):
|
||||||
if field_name not in self._meta.fields_map.keys():
|
if field_name not in self._meta.fields_map.keys():
|
||||||
raise Exception('Field %s not found in model' % field_name)
|
raise Exception('Field %s not found in model %s' % (field_name, self._meta.type_name))
|
||||||
custom_resolve_fn = 'resolve_%s' % field_name
|
custom_resolve_fn = 'resolve_%s' % field_name
|
||||||
if hasattr(self, custom_resolve_fn):
|
if hasattr(self, custom_resolve_fn):
|
||||||
resolve_fn = getattr(self, custom_resolve_fn)
|
resolve_fn = getattr(self, custom_resolve_fn)
|
||||||
|
|
|
@ -41,3 +41,47 @@ def to_camel_case(snake_str):
|
||||||
# We capitalize the first letter of each component except the first one
|
# We capitalize the first letter of each component except the first one
|
||||||
# with the 'title' method and join them together.
|
# with the 'title' method and join them together.
|
||||||
return components[0] + "".join(x.title() for x in components[1:])
|
return components[0] + "".join(x.title() for x in components[1:])
|
||||||
|
|
||||||
|
|
||||||
|
class LazyMap(object):
|
||||||
|
def __init__(self, origin, _map, state=None):
|
||||||
|
self._origin = origin
|
||||||
|
self._origin_iter = origin.__iter__()
|
||||||
|
self._state = state or []
|
||||||
|
self._finished = False
|
||||||
|
self._map = _map
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self if not self._finished else iter(self._state)
|
||||||
|
|
||||||
|
def iter(self):
|
||||||
|
return self.__iter__()
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self._origin.__len__()
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
try:
|
||||||
|
n = next(self._origin_iter)
|
||||||
|
n = self._map(n)
|
||||||
|
except StopIteration as e:
|
||||||
|
self._finished = True
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
self._state.append(n)
|
||||||
|
return n
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
return self.__next__()
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
item = self._origin.__getitem__(key)
|
||||||
|
if isinstance(key, slice):
|
||||||
|
return LazyMap(item, self._map)
|
||||||
|
return self._map(item)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self._origin, name)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<LazyMap %s>" % repr(self._origin)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user