diff --git a/docs/changelog.rst b/docs/changelog.rst index e2ecceeb..f3a4b944 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -53,7 +53,7 @@ Changes in dev - Added reverse delete rules - Fixed issue with unset operation - Fixed Q-object bug -- Added ``QuerySet.all_fields`` resets previous .only() and .exlude() +- Added ``QuerySet.all_fields`` resets previous .only() and .exclude() - Added ``QuerySet.exclude`` - Added django style choices - Fixed order and filter issue diff --git a/mongoengine/base.py b/mongoengine/base.py index ea0f98a4..e224367c 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -721,12 +721,18 @@ class BaseDocument(object): field = getattr(self, field_name, None) if isinstance(field, EmbeddedDocument) and db_field_name not in _changed_fields: # Grab all embedded fields that have been changed _changed_fields += ["%s%s" % (key, k) for k in field._get_changed_fields(key) if k] - elif isinstance(field, (list, tuple)) and db_field_name not in _changed_fields: # Loop list fields as they contain documents - for index, value in enumerate(field): + elif isinstance(field, (list, tuple, dict)) and db_field_name not in _changed_fields: # Loop list / dict fields as they contain documents + # Determine the iterator to use + if not hasattr(field, 'items'): + iterator = enumerate(field) + else: + iterator = field.iteritems() + for index, value in iterator: if not hasattr(value, '_get_changed_fields'): continue list_key = "%s%s." % (key, index) _changed_fields += ["%s%s" % (list_key, k) for k in value._get_changed_fields(list_key) if k] + return _changed_fields def _delta(self): @@ -736,7 +742,6 @@ class BaseDocument(object): # Handles cases where not loaded from_son but has _id doc = self.to_mongo() set_fields = self._get_changed_fields() - set_data = {} unset_data = {} if hasattr(self, '_changed_fields'): @@ -775,7 +780,7 @@ class BaseDocument(object): for p in parts: if p.isdigit(): d = d[int(p)] - elif hasattr(d, '__getattribute__'): + elif hasattr(d, '__getattribute__') and not isinstance(d, dict): real_path = d._reverse_db_field_map.get(p, p) d = getattr(d, real_path) else: diff --git a/tests/document.py b/tests/document.py index 5789e204..1c9b90ed 100644 --- a/tests/document.py +++ b/tests/document.py @@ -1504,6 +1504,18 @@ class DocumentTest(unittest.TestCase): del(doc.embedded_field.list_field[2].list_field) self.assertEquals(doc._delta(), ({}, {'embedded_field.list_field.2.list_field': 1})) + doc.save() + doc.reload() + + doc.dict_field['Embedded'] = embedded_1 + doc.save() + doc.reload() + + doc.dict_field['Embedded'].string_field = 'Hello World' + self.assertEquals(doc._get_changed_fields(), ['dict_field.Embedded.string_field']) + self.assertEquals(doc._delta(), ({'dict_field.Embedded.string_field': 'Hello World'}, {})) + + def test_delta_db_field(self): class Doc(Document): @@ -1795,7 +1807,8 @@ class DocumentTest(unittest.TestCase): person.save() person = self.Person.objects.get() - self.assertTrue(person.comments_dict['first_post'].published) + self.assertFalse(person.comments_dict['first_post'].published) + def test_delete(self): """Ensure that document may be deleted using the delete method. """