Skip to content

Commit 19dc312

Browse files
author
Omer Katz
committed
Merge pull request #927 from Catstyle/feature/mark_as_changed_issue
mark_as_changed issue
2 parents 8fea2b0 + 1756596 commit 19dc312

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,4 @@ that much better:
220220
* J. Fernando Sánchez (https://github.com/balkian)
221221
* Michael Chase (https://github.com/rxsegrxup)
222222
* Eremeev Danil (https://github.com/elephanter)
223+
* Catstyle Lee (https://github.com/Catstyle)

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55

66
Changes in 0.9.X - DEV
77
======================
8+
- Fixed mark_as_changed to handle higher/lower level fields changed. #927
89
- ListField of embedded docs doesn't set the _instance attribute when iterating over it #914
910
- Support += and *= for ListField #595
1011
- Use sets for populating dbrefs to dereference

mongoengine/base/document.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,19 @@ def _mark_as_changed(self, key):
483483
key = self._db_field_map.get(key, key)
484484

485485
if key not in self._changed_fields:
486-
self._changed_fields.append(key)
486+
levels, idx = key.split('.'), 1
487+
while idx <= len(levels):
488+
if '.'.join(levels[:idx]) in self._changed_fields:
489+
break
490+
idx += 1
491+
else:
492+
self._changed_fields.append(key)
493+
# remove lower level changed fields
494+
level = '.'.join(levels[:idx]) + '.'
495+
remove = self._changed_fields.remove
496+
for field in self._changed_fields:
497+
if field.startswith(level):
498+
remove(field)
487499

488500
def _clear_changed_fields(self):
489501
"""Using get_changed_fields iterate and remove any fields that are

tests/document/delta.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,56 @@ class MyDoc(Document):
735735
mydoc._clear_changed_fields()
736736
self.assertEqual([], mydoc._get_changed_fields())
737737

738+
def test_lower_level_mark_as_changed(self):
739+
class EmbeddedDoc(EmbeddedDocument):
740+
name = StringField()
741+
742+
class MyDoc(Document):
743+
subs = MapField(EmbeddedDocumentField(EmbeddedDoc))
744+
745+
MyDoc.drop_collection()
746+
747+
MyDoc().save()
748+
749+
mydoc = MyDoc.objects.first()
750+
mydoc.subs['a'] = EmbeddedDoc()
751+
self.assertEqual(["subs.a"], mydoc._get_changed_fields())
752+
753+
subdoc = mydoc.subs['a']
754+
subdoc.name = 'bar'
755+
756+
self.assertEqual(["name"], subdoc._get_changed_fields())
757+
self.assertEqual(["subs.a"], mydoc._get_changed_fields())
758+
mydoc.save()
759+
760+
mydoc._clear_changed_fields()
761+
self.assertEqual([], mydoc._get_changed_fields())
762+
763+
def test_upper_level_mark_as_changed(self):
764+
class EmbeddedDoc(EmbeddedDocument):
765+
name = StringField()
766+
767+
class MyDoc(Document):
768+
subs = MapField(EmbeddedDocumentField(EmbeddedDoc))
769+
770+
MyDoc.drop_collection()
771+
772+
MyDoc(subs={'a': EmbeddedDoc(name='foo')}).save()
773+
774+
mydoc = MyDoc.objects.first()
775+
subdoc = mydoc.subs['a']
776+
subdoc.name = 'bar'
777+
778+
self.assertEqual(["name"], subdoc._get_changed_fields())
779+
self.assertEqual(["subs.a.name"], mydoc._get_changed_fields())
780+
781+
mydoc.subs['a'] = EmbeddedDoc()
782+
self.assertEqual(["subs.a"], mydoc._get_changed_fields())
783+
mydoc.save()
784+
785+
mydoc._clear_changed_fields()
786+
self.assertEqual([], mydoc._get_changed_fields())
787+
738788
def test_referenced_object_changed_attributes(self):
739789
"""Ensures that when you save a new reference to a field, the referenced object isn't altered"""
740790

0 commit comments

Comments
 (0)