mongoengine icon indicating copy to clipboard operation
mongoengine copied to clipboard

DictField _auto_dereference gets changed after first query

Open bagerard opened this issue 1 year ago • 0 comments

The _auto_dereference flag of DictField defaults to False, but it gets overwritten to True (permanently) after any Doc gets loading through a Queryset

    def test_dictfield_dump_document_with_inheritance__cls(self):
        """Ensure a DictField can handle another document's dump."""

        class Doc(Document):
            field = DictField()

        class ToEmbedParent(Document):
            id = IntField(primary_key=True)
            recursive = DictField()

            meta = {"allow_inheritance": True}

        class ToEmbedChild(ToEmbedParent):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)

        Doc.drop_collection()
        ToEmbedParent.drop_collection()

        # with a Document with a _cls field
        to_embed_recursive = ToEmbedChild(id=1).save()
        to_embed_child = ToEmbedChild(
            id=2, recursive=to_embed_recursive.to_mongo().to_dict()
        ).save()

        doc_dump_as_dict = to_embed_child.to_mongo().to_dict()
        doc = Doc(field=doc_dump_as_dict)
        assert Doc.field._auto_dereference is False
        assert isinstance(doc.field, dict)  # depends on auto_dereference
        doc.save()
        assert isinstance(doc.field, dict)
        expected = {
            "_id": 2,
            "_cls": "ToEmbedParent.ToEmbedChild",
            "recursive": {
                "_id": 1,
                "_cls": "ToEmbedParent.ToEmbedChild",
                "recursive": {},
            },
        }
        assert doc.field == expected

       # Now after querying
        _ = Doc.objects.first()
        assert Doc.field._auto_dereference is False   # Fails
        doc = Doc(field=doc_dump_as_dict)
        assert isinstance(doc.field, dict)                       # Fails 

This has consequence on how it loads an EmbeddedDocument with inheritance afterward. It is due to this part , which mutates the original field's auto_deref flag for DictField (not only in case of copies of the Fields as it should)

image

bagerard avatar Aug 21 '24 13:08 bagerard