diff --git a/mongoengine/dereference.py b/mongoengine/dereference.py index 18b365ccd..c4b792559 100644 --- a/mongoengine/dereference.py +++ b/mongoengine/dereference.py @@ -104,7 +104,10 @@ def _find_references(self, items, depth=0): # LazyReference inherits DBRef but should not be dereferenced here ! continue elif isinstance(v, DBRef): - reference_map.setdefault(field.document_type, set()).add(v.id) + if hasattr(v, 'cls'): + reference_map.setdefault(get_document(v.cls), set()).add(v.id) + else: + reference_map.setdefault(field.document_type, set()).add(v.id) elif isinstance(v, (dict, SON)) and '_ref' in v: reference_map.setdefault(get_document(v['_cls']), set()).add(v['_ref'].id) elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth: @@ -112,13 +115,17 @@ def _find_references(self, items, depth=0): references = self._find_references(v, depth) for key, refs in references.iteritems(): if isinstance(field_cls, (Document, TopLevelDocumentMetaclass)): - key = field_cls + if not field_cls._meta.get('abstract', False): + key = field_cls reference_map.setdefault(key, set()).update(refs) elif isinstance(item, LazyReference): # LazyReference inherits DBRef but should not be dereferenced here ! continue elif isinstance(item, DBRef): - reference_map.setdefault(item.collection, set()).add(item.id) + if hasattr(item, 'cls'): + reference_map.setdefault(get_document(item.cls), set()).add(item.id) + else: + reference_map.setdefault(item.collection, set()).add(item.id) elif isinstance(item, (dict, SON)) and '_ref' in item: reference_map.setdefault(get_document(item['_cls']), set()).add(item['_ref'].id) elif isinstance(item, (dict, list, tuple)) and depth - 1 <= self.max_depth: diff --git a/mongoengine/fields.py b/mongoengine/fields.py index a661874a5..6e652ec16 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -2257,7 +2257,11 @@ def build_lazyref(self, value): if isinstance(value, self.document_type): value = LazyReference(self.document_type, value.pk, passthrough=self.passthrough) elif isinstance(value, DBRef): - value = LazyReference(self.document_type, value.id, passthrough=self.passthrough) + # Honor cls field on DBRef for Abstract Documents + if hasattr(value, 'cls'): + value = LazyReference(get_document(value.cls), value.id, passthrough=self.passthrough) + else: + LazyReference(self.document_type, value.id, passthrough=self.passthrough) else: # value is the primary key of the referenced document value = LazyReference(self.document_type, value, passthrough=self.passthrough) @@ -2302,7 +2306,10 @@ def validate(self, value): pk = value.pk elif isinstance(value, DBRef): # TODO: check collection ? - collection = self.document_type._get_collection_name() + if hasattr(value, 'cls'): + collection = get_document(value.cls)._get_collection_name() + else: + collection = self.document_type._get_collection_name() if value.collection != collection: self.error("DBRef on bad collection (must be on `%s`)" % collection) pk = value.id