mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-30 23:47:55 +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