From 823cf421fac4bd1a20b3b10bd4347b74e7bcf857 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Thu, 29 Sep 2011 14:07:30 -0700 Subject: [PATCH] Fixes to circular references. Removes infinite looping refs #294 --- mongoengine/dereference.py | 6 ++-- tests/dereference.py | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) 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):