mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 01:47:45 +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.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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,17 +22,26 @@ def get_type_for_model(schema, model):
 | 
			
		|||
            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):
 | 
			
		||||
        if isinstance(value, (QuerySet, Manager)):
 | 
			
		||||
            cls = instance.__class__
 | 
			
		||||
            value = [cls(s) for s in value.all()]
 | 
			
		||||
        return value
 | 
			
		||||
        return lazy_map(value, instance.__class__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
 | 
			
		||||
    @memoize
 | 
			
		||||
    def get_field(self, schema):
 | 
			
		||||
        model_field = self.field_type
 | 
			
		||||
| 
						 | 
				
			
			@ -40,13 +49,12 @@ class ConnectionOrListField(LazyField):
 | 
			
		|||
        if field_object_type and issubclass(field_object_type, BaseNode):
 | 
			
		||||
            field = DjangoConnectionField(model_field)
 | 
			
		||||
        else:
 | 
			
		||||
            field = ListField(model_field)
 | 
			
		||||
            field = LazyListField(model_field)
 | 
			
		||||
        field.contribute_to_class(self.object_type, self.name)
 | 
			
		||||
        return field
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DjangoModelField(Field):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, model, *args, **kwargs):
 | 
			
		||||
        super(DjangoModelField, self).__init__(None, *args, **kwargs)
 | 
			
		||||
        self.model = model
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,6 +101,8 @@ class BaseObjectType(object):
 | 
			
		|||
            raise Exception("An interface cannot be initialized")
 | 
			
		||||
        if instance is None:
 | 
			
		||||
            return None
 | 
			
		||||
        elif type(instance) is cls:
 | 
			
		||||
            instance = instance.instance
 | 
			
		||||
        return super(BaseObjectType, cls).__new__(cls, instance, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, instance=None):
 | 
			
		||||
| 
						 | 
				
			
			@ -115,9 +117,12 @@ class BaseObjectType(object):
 | 
			
		|||
    def get_field(self, field):
 | 
			
		||||
        return getattr(self.instance, field, None)
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self.instance.__eq__(other)
 | 
			
		||||
 | 
			
		||||
    def resolve(self, field_name, args, info):
 | 
			
		||||
        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
 | 
			
		||||
        if hasattr(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
 | 
			
		||||
    # with the 'title' method and join them together.
 | 
			
		||||
    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