Updating an inner dict within a `DictField` of a `DynamicDocument` raise an `AttributeError`
karimelhajoui63 opened this issue · 0 comments
Hi,
Details:
I have an issue with the updating of a DictField
of a DynamicDocument
that sometimes raises an exception.
It seems that there is a bug in mongoengine
(more precisely in the _changed_fields
) when we try to update a key of an inner dict, within the DictField that is at the top level of the Document
.
As far as I dug, it seems to be because the inner dict is considered as a BaseDict
, so when it is updated, the inner dict is added to _changed_fields
but this inner dict isn't a field of the document, so there is an AttributeError
on save()
(see traceback below).
One more thing: this seem to be the case only with DynamicDocument
and not with Document
. And there is also no exception raised when the document came from the database.
Tested on versions:
- Python
3.10.13
- MongoEngine
0.27.0
- PyMongo
4.6.1
Code to reproduce the bug:
from mongoengine import connect, DictField, DynamicDocument
connect("test", host="mongodb://localhost:27018/test")
class ExampleModel(DynamicDocument): # but there is no exception at all with `Document`
root_dict = DictField(default=None)
ExampleModel.objects().delete() # just in case
example = ExampleModel()
example.root_dict = {"inner_dict":{"key": "value"}}
example.save() # ✅
if example.root_dict["inner_dict"]["key"]:
print("'inner_dict' is present in 'example'")
# ------------------
# example.reload() # <-- with this line uncommented, no exception is raised
example.root_dict["inner_dict"]["key"] = "NEW_value"
try:
example.save() # raise "AttributeError" ❌
except AttributeError as exc:
print(exc)
else:
print("No exception for 'example'")
# ------------------
example_from_db = ExampleModel.objects().first()
example_from_db.root_dict["inner_dict"]["key"] = "NEW_value"
try:
example_from_db.save() # don't raise any exception ✅
except AttributeError as exc:
print(exc)
else:
print("No exception for 'example_from_db'")
Output of this program:
'inner_dict' is present in 'example'
'ExampleModel' object has no attribute 'inner_dict'
No exception for 'example_from_db'
Complete traceback of the error on .save()
:
Traceback (most recent call last):
File "/workspaces/bin/personal/mongoengine_dictfield.py", line 23, in <module>
example.save()
File "/workspaces/.venv/lib/python3.10/site-packages/mongoengine/document.py", line 429, in save
object_id, created = self._save_update(
File "/workspaces/.venv/lib/python3.10/site-packages/mongoengine/document.py", line 545, in _save_update
update_doc = self._get_update_doc()
File "/workspaces/.venv/lib/python3.10/site-packages/mongoengine/document.py", line 501, in _get_update_doc
updates, removals = self._delta()
File "/workspaces/.venv/lib/python3.10/site-packages/mongoengine/base/document.py", line 746, in _delta
d = getattr(d, real_path)
AttributeError: 'ExampleModel' object has no attribute 'inner_dict'