diff --git a/docs/changelog.rst b/docs/changelog.rst index 69581a4b..255d3743 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,8 @@ Development =========== - QuerySet limit function behaviour: Passing 0 as parameter will return all the documents in the cursor #1611 - bulk insert updates the ids of the input documents #1919 +- Fix an harmless bug related to GenericReferenceField where modifications in the generic-referenced document + were tracked in the parent (#1934) - (Fill this out as you fix issues and develop your features). ======= Changes in 0.15.4 diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 66217921..aad027e5 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -528,6 +528,7 @@ class BaseDocument(object): EmbeddedDocument = _import_class('EmbeddedDocument') DynamicEmbeddedDocument = _import_class('DynamicEmbeddedDocument') ReferenceField = _import_class('ReferenceField') + GenericReferenceField = _import_class('GenericReferenceField') SortedListField = _import_class('SortedListField') changed_fields = [] @@ -560,7 +561,7 @@ class BaseDocument(object): elif (isinstance(data, (list, tuple, dict)) and db_field_name not in changed_fields): if (hasattr(field, 'field') and - isinstance(field.field, ReferenceField)): + isinstance(field.field, (ReferenceField, GenericReferenceField))): continue elif isinstance(field, SortedListField) and field._ordering: # if ordering is affected whole list is changed diff --git a/tests/fields/fields.py b/tests/fields/fields.py index b375822e..084be71f 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -1187,7 +1187,7 @@ class FieldTest(MongoDBTestCase): # aka 'del list[index]' # aka 'operator.delitem(list, index)' reset_post() - del post.info[2] # del from middle ('2') + del post.info[2] # del from middle ('2') self.assertEqual(post.info, ['0', '1', '3', '4', '5']) post.save() post.reload() @@ -1197,7 +1197,7 @@ class FieldTest(MongoDBTestCase): # aka 'del list[i:j]' # aka 'operator.delitem(list, slice(i,j))' reset_post() - del post.info[1:3] # removes '1', '2' + del post.info[1:3] # removes '1', '2' self.assertEqual(post.info, ['0', '3', '4', '5']) post.save() post.reload() @@ -2816,7 +2816,32 @@ class FieldTest(MongoDBTestCase): doc = Doc.objects.get(ref=DBRef('doc', doc1.pk)) self.assertEqual(doc, doc2) - def test_generic_reference_filter_by_objectid(self): + def test_generic_reference_is_not_tracked_in_parent_doc(self): + """Ensure that modifications of related documents (through generic reference) don't influence + the owner changed fields (#1934) + """ + class Doc1(Document): + name = StringField() + + class Doc2(Document): + ref = GenericReferenceField() + refs = ListField(GenericReferenceField()) + + Doc1.drop_collection() + Doc2.drop_collection() + + doc1 = Doc1(name='garbage1').save() + doc11 = Doc1(name='garbage11').save() + doc2 = Doc2(ref=doc1, refs=[doc11]).save() + + doc2.ref.name = 'garbage2' + self.assertEqual(doc2._get_changed_fields(), []) + + doc2.refs[0].name = 'garbage3' + self.assertEqual(doc2._get_changed_fields(), []) + self.assertEqual(doc2._delta(), ({}, {})) + + def test_generic_reference_field(self): """Ensure we can search for a specific generic reference by providing its DBRef. """ @@ -4348,6 +4373,7 @@ class TestEmbeddedDocumentField(MongoDBTestCase): class MyFailingdoc2(Document): emb = EmbeddedDocumentField('MyDoc') + class CachedReferenceFieldTest(MongoDBTestCase): def test_cached_reference_field_get_and_save(self):