Cheaply dereferences the items to a set depth. Also handles the conversion of complex data types. :param items: The iterable (dict, list, queryset) to be dereferenced. :param max_depth: The maximum depth to recurse to :param instance: The owning instance use
(self, items, max_depth=1, instance=None, name=None)
| 21 | |
| 22 | class DeReference: |
| 23 | def __call__(self, items, max_depth=1, instance=None, name=None): |
| 24 | """ |
| 25 | Cheaply dereferences the items to a set depth. |
| 26 | Also handles the conversion of complex data types. |
| 27 | |
| 28 | :param items: The iterable (dict, list, queryset) to be dereferenced. |
| 29 | :param max_depth: The maximum depth to recurse to |
| 30 | :param instance: The owning instance used for tracking changes by |
| 31 | :class:`~mongoengine.base.ComplexBaseField` |
| 32 | :param name: The name of the field, used for tracking changes by |
| 33 | :class:`~mongoengine.base.ComplexBaseField` |
| 34 | :param get: A boolean determining if being called by __get__ |
| 35 | """ |
| 36 | if items is None or isinstance(items, str): |
| 37 | return items |
| 38 | |
| 39 | # cheapest way to convert a queryset to a list |
| 40 | # list(queryset) uses a count() query to determine length |
| 41 | if isinstance(items, QuerySet): |
| 42 | items = [i for i in items] |
| 43 | |
| 44 | self.max_depth = max_depth |
| 45 | doc_type = None |
| 46 | |
| 47 | if instance and isinstance( |
| 48 | instance, (Document, EmbeddedDocument, TopLevelDocumentMetaclass) |
| 49 | ): |
| 50 | doc_type = instance._fields.get(name) |
| 51 | while hasattr(doc_type, "field"): |
| 52 | doc_type = doc_type.field |
| 53 | |
| 54 | if isinstance(doc_type, ReferenceField): |
| 55 | field = doc_type |
| 56 | doc_type = doc_type.document_type |
| 57 | is_list = not hasattr(items, "items") |
| 58 | |
| 59 | if is_list and all(i.__class__ == doc_type for i in items): |
| 60 | return items |
| 61 | elif not is_list and all( |
| 62 | i.__class__ == doc_type for i in items.values() |
| 63 | ): |
| 64 | return items |
| 65 | elif not field.dbref: |
| 66 | # We must turn the ObjectIds into DBRefs |
| 67 | |
| 68 | # Recursively dig into the sub items of a list/dict |
| 69 | # to turn the ObjectIds into DBRefs |
| 70 | def _get_items_from_list(items): |
| 71 | new_items = [] |
| 72 | for v in items: |
| 73 | value = v |
| 74 | if isinstance(v, dict): |
| 75 | value = _get_items_from_dict(v) |
| 76 | elif isinstance(v, list): |
| 77 | value = _get_items_from_list(v) |
| 78 | elif not isinstance(v, (DBRef, Document)): |
| 79 | value = field.to_python(v) |
| 80 | new_items.append(value) |
nothing calls this directly
no test coverage detected