From 3b8489a7ec59d60f66c6165f14cea35839ea71d7 Mon Sep 17 00:00:00 2001 From: Jon Scott Date: Thu, 9 Aug 2012 17:30:12 +0100 Subject: [PATCH 1/3] Set _parent on EmbeddedDocument instances --- mongoengine/base.py | 14 ++++++++++++-- mongoengine/fields.py | 7 +++++++ tests/test_fields.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/mongoengine/base.py b/mongoengine/base.py index 6fb26cb7c..b7982b8c9 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -1320,13 +1320,23 @@ def clear(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).clear(*args, **kwargs) + def _get_wrapper(self, value): + from mongoengine import EmbeddedDocument + if isinstance(value, EmbeddedDocument) and self._instance is not None: + value._parent = self._instance + return value + + def __getitem__(self, *args, **kwargs): + return self._get_wrapper( + super(BaseDict, self).__getitem__(*args, **kwargs)) + def pop(self, *args, **kwargs): self._mark_as_changed() - return super(BaseDict, self).pop(*args, **kwargs) + return self._get_wrapper(super(BaseDict, self).pop(*args, **kwargs)) def popitem(self, *args, **kwargs): self._mark_as_changed() - return super(BaseDict, self).popitem(*args, **kwargs) + return self._get_wrapper(super(BaseDict, self).popitem(*args, **kwargs)) def update(self, *args, **kwargs): self._mark_as_changed() diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 8e3cf15a5..f6a99cf46 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -418,6 +418,13 @@ def document_type(self): self.document_type_obj = get_document(self.document_type_obj) return self.document_type_obj + def __get__(self, instance, owner): + value = super(EmbeddedDocumentField, self).__get__(instance, owner) + if (isinstance(value, EmbeddedDocument) + and value is not None and instance is not None): + value._parent = instance + return value + def to_python(self, value): if not isinstance(value, self.document_type): return self.document_type._from_son(value) diff --git a/tests/test_fields.py b/tests/test_fields.py index a6eaca434..b136a6fb7 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -2174,6 +2174,40 @@ class Post(Document): post.comments[1].content = 'here we go' post.validate() + def test_embedded_document_parent(self): + """Ensure that embedded documents receive a link back to their parent. + """ + class Child(EmbeddedDocument): + name = StringField(required=True) + + class Parent(EmbeddedDocument): + name = StringField(required=True) + child = EmbeddedDocumentField(Child) + + parent = Parent(name='parent', child=Child(name='child')) + + self.assertEquals(parent.child._parent.name, 'parent') + + + def test_embedded_document_map_parent(self): + """Ensure that embedded documents in MapFields receive a link back + to their parent. + """ + class Child(EmbeddedDocument): + name = StringField(required=True) + + class Parent(EmbeddedDocument): + name = StringField(required=True) + children = MapField(EmbeddedDocumentField(Child)) + + parent = Parent(name='parent', children={ + 'c1': Child(name='child1'), + 'c2': Child(name='child2'), + }) + + self.assertEquals(parent.children['c1']._parent.name, 'parent') + self.assertEquals(parent.children['c2']._parent.name, 'parent') + if __name__ == '__main__': unittest.main() From 7db426268efbcc48fdfade6623a9c1c93eb3fd44 Mon Sep 17 00:00:00 2001 From: Alex Kelly Date: Tue, 30 Apr 2013 21:13:49 +0100 Subject: [PATCH 2/3] Pass write_concern parameter from update_one --- mongoengine/queryset/queryset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mongoengine/queryset/queryset.py b/mongoengine/queryset/queryset.py index bfb5a4866..1739f05e1 100644 --- a/mongoengine/queryset/queryset.py +++ b/mongoengine/queryset/queryset.py @@ -469,7 +469,8 @@ def update_one(self, upsert=False, write_concern=None, **update): .. versionadded:: 0.2 """ - return self.update(upsert=upsert, multi=False, write_concern=None, **update) + return self.update( + upsert=upsert, multi=False, write_concern=write_concern, **update) def with_id(self, object_id): """Retrieve the object matching the id provided. Uses `object_id` only From c5de08ff9cc49836ee7b75f05715df3161e0d8e0 Mon Sep 17 00:00:00 2001 From: Alex Kelly Date: Tue, 30 Apr 2013 21:36:43 +0100 Subject: [PATCH 3/3] Updated tests for passing write_concern to update and update_one to check return. --- tests/queryset/queryset.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index 40aef7ecd..7ca0596a9 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -287,15 +287,19 @@ def test_update_write_concern(self): name='Test User', write_concern=write_concern) author.save(write_concern=write_concern) - self.Person.objects.update(set__name='Ross', - write_concern=write_concern) - - author = self.Person.objects.first() - self.assertEqual(author.name, 'Ross') - - self.Person.objects.update_one(set__name='Test User', write_concern=write_concern) - author = self.Person.objects.first() - self.assertEqual(author.name, 'Test User') + result = self.Person.objects.update( + set__name='Ross',write_concern={"w": 1}) + self.assertEqual(result, 1) + result = self.Person.objects.update( + set__name='Ross',write_concern={"w": 0}) + self.assertEqual(result, None) + + result = self.Person.objects.update_one( + set__name='Test User', write_concern={"w": 1}) + self.assertEqual(result, 1) + result = self.Person.objects.update_one( + set__name='Test User', write_concern={"w": 0}) + self.assertEqual(result, None) def test_update_update_has_a_value(self): """Test to ensure that update is passed a value to update to"""