Example #1
0
 def _reload(self, key, value):
     """Used by :meth:`~mongoengine.Document.reload` to ensure the
     correct instance is linked to self.
     """
     if isinstance(value, BaseDict):
         value = [(k, self._reload(k, v)) for k, v in value.items()]
         value = BaseDict(value, self, key)
     elif isinstance(value, BaseList):
         value = [self._reload(key, v) for v in value]
         value = BaseList(value, self, key)
     elif isinstance(value, (EmbeddedDocument, DynamicEmbeddedDocument)):
         value._changed_fields = []
     return value
Example #2
0
 def _reload(self, key, value):
     """Used by :meth:`~mongoengine.Document.reload` to ensure the
     correct instance is linked to self.
     """
     if isinstance(value, BaseDict):
         value = [(k, self._reload(k, v)) for k, v in value.items()]
         value = BaseDict(value, self, key)
     elif isinstance(value, BaseList):
         value = [self._reload(key, v) for v in value]
         value = BaseList(value, self, key)
     elif isinstance(value, (EmbeddedDocument, DynamicEmbeddedDocument)):
         value._changed_fields = []
     return value
Example #3
0
    def _attach_objects(self,
                        items,
                        depth=0,
                        instance=None,
                        name=None,
                        get=False):
        """
        Recursively finds all db references to be dereferenced

        :param items: The iterable (dict, list, queryset)
        :param depth: The current depth of recursion
        :param instance: The owning instance used for tracking changes by
            :class:`~mongoengine.base.ComplexBaseField`
        :param name: The name of the field, used for tracking changes by
            :class:`~mongoengine.base.ComplexBaseField`
        :param get: A boolean determining if being called by __get__
        """
        if not items:
            if isinstance(items, (BaseDict, BaseList)):
                return items

            if instance:
                if isinstance(items, dict):
                    return BaseDict(items, instance=instance, name=name)
                else:
                    return BaseList(items, instance=instance, name=name)

        if isinstance(items, (dict, pymongo.son.SON)):
            if '_ref' in items:
                return self.object_map.get(items['_ref'].id, items)
            elif '_types' in items and '_cls' in items:
                doc = get_document(items['_cls'])._from_son(items)
                if not get:
                    doc._data = self._attach_objects(doc._data, depth, doc,
                                                     name, get)
                return doc

        if not hasattr(items, 'items'):
            is_list = True
            iterator = enumerate(items)
            data = []
        else:
            is_list = False
            iterator = items.iteritems()
            data = {}

        for k, v in iterator:
            if is_list:
                data.append(v)
            else:
                data[k] = v

            if k in self.object_map:
                data[k] = self.object_map[k]
            elif hasattr(v, '_fields'):
                for field_name, field in v._fields.iteritems():
                    v = data[k]._data.get(field_name, None)
                    if isinstance(v, (pymongo.dbref.DBRef)):
                        data[k]._data[field_name] = self.object_map.get(
                            v.id, v)
                    elif isinstance(v,
                                    (dict, pymongo.son.SON)) and '_ref' in v:
                        data[k]._data[field_name] = self.object_map.get(
                            v['_ref'].id, v)
                    elif isinstance(v, dict) and depth < self.max_depth:
                        data[k]._data[field_name] = self._attach_objects(
                            v, depth, instance=instance, name=name, get=get)
                    elif isinstance(v, (list, tuple)):
                        data[k]._data[field_name] = self._attach_objects(
                            v, depth, instance=instance, name=name, get=get)
            elif isinstance(v, (dict, list, tuple)) and depth < self.max_depth:
                data[k] = self._attach_objects(v,
                                               depth,
                                               instance=instance,
                                               name=name,
                                               get=get)
            elif hasattr(v, 'id'):
                data[k] = self.object_map.get(v.id, v)

        if instance and name:
            if is_list:
                return BaseList(data, instance=instance, name=name)
            return BaseDict(data, instance=instance, name=name)
        depth += 1
        return data
Example #4
0
    def _attach_objects(self, items, depth=0, instance=None, name=None):
        """
        Recursively finds all db references to be dereferenced

        :param items: The iterable (dict, list, queryset)
        :param depth: The current depth of recursion
        :param instance: The owning instance used for tracking changes by
            :class:`~mongoengine.base.ComplexBaseField`
        :param name: The name of the field, used for tracking changes by
            :class:`~mongoengine.base.ComplexBaseField`
        """
        if not items:
            if isinstance(items, (BaseDict, BaseList)):
                return items

            if instance:
                if isinstance(items, dict):
                    return BaseDict(items, instance, name)
                else:
                    return BaseList(items, instance, name)

        if isinstance(items, (dict, SON)):
            if '_ref' in items:
                return self.object_map.get(items['_ref'].id, items)
            elif '_cls' in items:
                doc = get_document(items['_cls'])._from_son(items)
                _cls = doc._data.pop('_cls', None)
                del items['_cls']
                doc._data = self._attach_objects(doc._data, depth, doc, None)
                if _cls is not None:
                    doc._data['_cls'] = _cls
                return doc

        if not hasattr(items, 'items'):
            is_list = True
            list_type = BaseList
            if isinstance(items, EmbeddedDocumentList):
                list_type = EmbeddedDocumentList
            as_tuple = isinstance(items, tuple)
            iterator = enumerate(items)
            data = []
        else:
            is_list = False
            iterator = items.iteritems()
            data = {}

        depth += 1
        for k, v in iterator:
            if is_list:
                data.append(v)
            else:
                data[k] = v

            if k in self.object_map and not is_list:
                data[k] = self.object_map[k]
            elif isinstance(v, (Document, EmbeddedDocument)):
                for field_name, field in v._fields.iteritems():
                    v = data[k]._data.get(field_name, None)
                    if isinstance(v, (DBRef)):
                        data[k]._data[field_name] = self.object_map.get(v.id, v)
                    elif isinstance(v, (dict, SON)) and '_ref' in v:
                        data[k]._data[field_name] = self.object_map.get(v['_ref'].id, v)
                    elif isinstance(v, dict) and depth <= self.max_depth:
                        data[k]._data[field_name] = self._attach_objects(v, depth, instance=instance, name=name)
                    elif isinstance(v, (list, tuple)) and depth <= self.max_depth:
                        data[k]._data[field_name] = self._attach_objects(v, depth, instance=instance, name=name)
            elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth:
                item_name = '%s.%s' % (name, k) if name else name
                data[k] = self._attach_objects(v, depth - 1, instance=instance, name=item_name)
            elif hasattr(v, 'id'):
                data[k] = self.object_map.get(v.id, v)

        if instance and name:
            if is_list:
                return tuple(data) if as_tuple else list_type(data, instance, name)
            return BaseDict(data, instance, name)
        depth += 1
        return data