Implement _get_as_pymongo
This commit is contained in:
		| @@ -354,6 +354,7 @@ class QuerySet(object): | |||||||
|         self._iter = False |         self._iter = False | ||||||
|         self._scalar = [] |         self._scalar = [] | ||||||
|         self._as_pymongo = False |         self._as_pymongo = False | ||||||
|  |         self._as_pymongo_coerce = False | ||||||
|  |  | ||||||
|         # If inheritance is allowed, only return instances and instances of |         # If inheritance is allowed, only return instances and instances of | ||||||
|         # subclasses of the class being used |         # subclasses of the class being used | ||||||
| @@ -1003,9 +1004,8 @@ class QuerySet(object): | |||||||
|             if self._scalar: |             if self._scalar: | ||||||
|                 return self._get_scalar(self._document._from_son( |                 return self._get_scalar(self._document._from_son( | ||||||
|                         self._cursor.next())) |                         self._cursor.next())) | ||||||
|  |  | ||||||
|             if self._as_pymongo: |             if self._as_pymongo: | ||||||
|                 return self._cursor.next() |                 return self._get_as_pymongo(self._cursor.next()) | ||||||
|  |  | ||||||
|             return self._document._from_son(self._cursor.next()) |             return self._document._from_son(self._cursor.next()) | ||||||
|         except StopIteration, e: |         except StopIteration, e: | ||||||
| @@ -1585,6 +1585,48 @@ class QuerySet(object): | |||||||
|  |  | ||||||
|         return tuple(data) |         return tuple(data) | ||||||
|  |  | ||||||
|  |     def _get_as_pymongo(self, row): | ||||||
|  |         # Extract which fields paths we should follow if .fields(...) was | ||||||
|  |         # used. If not, handle all fields. | ||||||
|  |         if not getattr(self, '__as_pymongo_fields', None): | ||||||
|  |             self.__as_pymongo_fields = [] | ||||||
|  |             for field in self._loaded_fields.fields - set(['_cls', '_id', '_types']): | ||||||
|  |                 self.__as_pymongo_fields.append(field) | ||||||
|  |                 while '.' in field: | ||||||
|  |                     field, _ = field.rsplit('.', 1) | ||||||
|  |                     self.__as_pymongo_fields.append(field) | ||||||
|  |  | ||||||
|  |         all_fields = not self.__as_pymongo_fields | ||||||
|  |  | ||||||
|  |         def clean(data, path=None): | ||||||
|  |             path = path or '' | ||||||
|  |  | ||||||
|  |             if isinstance(data, dict): | ||||||
|  |                 new_data = {} | ||||||
|  |                 for key, value in data.iteritems(): | ||||||
|  |                     new_path = '%s.%s' % (path, key) if path else key | ||||||
|  |                     if all_fields or new_path in self.__as_pymongo_fields: | ||||||
|  |                         new_data[key] = clean(value, path=new_path) | ||||||
|  |                 data = new_data | ||||||
|  |             elif isinstance(data, list): | ||||||
|  |                 data = [clean(d, path=path) for d in data] | ||||||
|  |             else: | ||||||
|  |                 if self._as_pymongo_coerce: | ||||||
|  |                     # If we need to coerce types, we need to determine the | ||||||
|  |                     # type of this field and use the corresponding .to_python(...) | ||||||
|  |                     from mongoengine.fields import EmbeddedDocumentField | ||||||
|  |                     obj = self._document | ||||||
|  |                     for chunk in path.split('.'): | ||||||
|  |                         obj = getattr(obj, chunk, None) | ||||||
|  |                         if obj is None: | ||||||
|  |                             break | ||||||
|  |                         elif isinstance(obj, EmbeddedDocumentField): | ||||||
|  |                             obj = obj.document_type | ||||||
|  |                     if obj and data is not None: | ||||||
|  |                         data = obj.to_python(data) | ||||||
|  |             return data | ||||||
|  |         return clean(row) | ||||||
|  |  | ||||||
|     def scalar(self, *fields): |     def scalar(self, *fields): | ||||||
|         """Instead of returning Document instances, return either a specific |         """Instead of returning Document instances, return either a specific | ||||||
|         value or a tuple of values in order. |         value or a tuple of values in order. | ||||||
| @@ -1607,11 +1649,14 @@ class QuerySet(object): | |||||||
|         """An alias for scalar""" |         """An alias for scalar""" | ||||||
|         return self.scalar(*fields) |         return self.scalar(*fields) | ||||||
|  |  | ||||||
|     def as_pymongo(self): |     def as_pymongo(self, coerce_types=False): | ||||||
|         """Instead of returning Document instances, return raw values from |         """Instead of returning Document instances, return raw values from | ||||||
|         pymongo. |         pymongo. | ||||||
|  |  | ||||||
|  |         :param coerce_type: Field types (if applicable) would be use to coerce types. | ||||||
|         """ |         """ | ||||||
|         self._as_pymongo = True |         self._as_pymongo = True | ||||||
|  |         self._as_pymongo_coerce = coerce_types | ||||||
|         return self |         return self | ||||||
|  |  | ||||||
|     def _sub_js_fields(self, code): |     def _sub_js_fields(self, code): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user