diff --git a/mongoengine/base/datastructures.py b/mongoengine/base/datastructures.py index a32f6040a..8f670e640 100644 --- a/mongoengine/base/datastructures.py +++ b/mongoengine/base/datastructures.py @@ -31,9 +31,9 @@ def mark_key_as_changed_wrapper(parent_method): def wrapper(self, key, *args, **kwargs): # Can't use super() in the decorator. - result = parent_method(self, key, *args, **kwargs) - self._mark_as_changed(key) - return result + if not args or not key or key not in self or self[key] != args[0]: + self._mark_as_changed(key) + return parent_method(self, key, *args, **kwargs) return wrapper diff --git a/tests/document/test_delta.py b/tests/document/test_delta.py index 68c698b64..537c86bfd 100644 --- a/tests/document/test_delta.py +++ b/tests/document/test_delta.py @@ -952,6 +952,31 @@ class Doc(Document): assert "oops" == delta[0]["users.007.rolist"][0]["type"] assert uinfo.id == delta[0]["users.007.info"] + def test_delta_on_dict(self): + class MyDoc(Document): + dico = DictField() + + MyDoc.drop_collection() + + MyDoc(dico={"a": {"b": 0}}).save() + + mydoc = MyDoc.objects.first() + assert mydoc._get_changed_fields() == [] + mydoc.dico["a"]["b"] = 0 + assert mydoc._get_changed_fields() == [] + mydoc.dico["a"] = {"b": 0} + assert mydoc._get_changed_fields() == [] + mydoc.dico = {"a": {"b": 0}} + assert mydoc._get_changed_fields() == [] + mydoc.dico["a"]["c"] = 1 + assert mydoc._get_changed_fields() == ["dico.a.c"] + mydoc.dico["a"]["b"] = 2 + mydoc.dico["d"] = 3 + assert mydoc._get_changed_fields() == ["dico.a.c", "dico.a.b", "dico.d"] + + mydoc._clear_changed_fields() + assert mydoc._get_changed_fields() == [] + if __name__ == "__main__": unittest.main()