diff --git a/docs/changelog.rst b/docs/changelog.rst index b7904bdc..0b93c74c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +Changes in v0.5.1 +================= + +- Circular reference bugfix + Changes in v0.5 =============== diff --git a/mongoengine/dereference.py b/mongoengine/dereference.py index 7fe9ba2f..949bb2f9 100644 --- a/mongoengine/dereference.py +++ b/mongoengine/dereference.py @@ -33,13 +33,15 @@ class DeReference(object): items = [i for i in items] self.max_depth = max_depth - + doc_type = None if instance and instance._fields: doc_type = instance._fields[name].field - + if isinstance(doc_type, ReferenceField): doc_type = doc_type.document_type + if all([i.__class__ == doc_type for i in items]): + return items self.reference_map = self._find_references(items) self.object_map = self._fetch_objects(doc_type=doc_type) diff --git a/tests/dereference.py b/tests/dereference.py index a98267fd..b85ca179 100644 --- a/tests/dereference.py +++ b/tests/dereference.py @@ -129,6 +129,65 @@ class FieldTest(unittest.TestCase): self.assertEquals(employee.friends, friends) self.assertEqual(q, 2) + def test_circular_reference(self): + """Ensure you can handle circular references + """ + class Person(Document): + name = StringField() + relations = ListField(EmbeddedDocumentField('Relation')) + + def __repr__(self): + return "" % self.name + + class Relation(EmbeddedDocument): + name = StringField() + person = ReferenceField('Person') + + Person.drop_collection() + mother = Person(name="Mother") + daughter = Person(name="Daughter") + + mother.save() + daughter.save() + + daughter_rel = Relation(name="Daughter", person=daughter) + mother.relations.append(daughter_rel) + mother.save() + + mother_rel = Relation(name="Daughter", person=mother) + self_rel = Relation(name="Self", person=daughter) + daughter.relations.append(mother_rel) + daughter.relations.append(self_rel) + daughter.save() + + self.assertEquals("[, ]", "%s" % Person.objects()) + + def test_circular_reference_on_self(self): + """Ensure you can handle circular references + """ + class Person(Document): + name = StringField() + relations = ListField(ReferenceField('self')) + + def __repr__(self): + return "" % self.name + + Person.drop_collection() + mother = Person(name="Mother") + daughter = Person(name="Daughter") + + mother.save() + daughter.save() + + mother.relations.append(daughter) + mother.save() + + daughter.relations.append(mother) + daughter.relations.append(daughter) + daughter.save() + + self.assertEquals("[, ]", "%s" % Person.objects()) + def test_generic_reference(self): class UserA(Document):