Merge pull request #1935 from bagerard/generic_ref_field_changed

Fix bug when doing modifications to generic-referenced document
This commit is contained in:
Bastien Gérard 2018-10-31 15:53:13 +01:00 committed by GitHub
commit 354cfe0f9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 7 deletions

View File

@ -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

View File

@ -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

View File

@ -1872,8 +1872,8 @@ class BaseQuerySet(object):
# Substitute the correct name for the field into the javascript
return '.'.join([f.db_field for f in fields])
code = re.sub(u'\[\s*~([A-z_][A-z_0-9.]+?)\s*\]', field_sub, code)
code = re.sub(u'\{\{\s*~([A-z_][A-z_0-9.]+?)\s*\}\}', field_path_sub,
code = re.sub(r'\[\s*~([A-z_][A-z_0-9.]+?)\s*\]', field_sub, code)
code = re.sub(r'\{\{\s*~([A-z_][A-z_0-9.]+?)\s*\}\}', field_path_sub,
code)
return code

View File

@ -5,7 +5,7 @@ detailed-errors=1
cover-package=mongoengine
[flake8]
ignore=E501,F401,F403,F405,I201,I202
ignore=E501,F401,F403,F405,I201,I202,W504, W605
exclude=build,dist,docs,venv,venv3,.tox,.eggs,tests
max-complexity=47
application-import-names=mongoengine,tests

View File

@ -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.
"""
@ -4345,6 +4370,7 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
class MyFailingdoc2(Document):
emb = EmbeddedDocumentField('MyDoc')
class CachedReferenceFieldTest(MongoDBTestCase):
def test_cached_reference_field_get_and_save(self):