MongoEngine/mongoengine

Validation doesn't work on embedded documents with inheritance

Closed this issue · 1 comments

Hi,

Apparently validation doesn't work if the validate method is overridden by a subclass of an embedded document.

Example:

import mongoengine


class BaseItem(mongoengine.EmbeddedDocument):
    f = mongoengine.IntField()

    meta = {
        'allow_inheritance': True
    }


class RealItem(BaseItem):
    a = mongoengine.IntField()

    def validate(self, clean=True):
        if self.f < 0:
            raise Exception()
        return super().validate(clean)


class TopLevel(mongoengine.Document):
    items = mongoengine.EmbeddedDocumentListField(document_type=BaseItem)


item = TopLevel(items=[RealItem(f=-1, a=0)])
item.validate()

Looking at the code, this happens because the EmbeddedDocumentField calls self.document_type.validate(value, clean) and not value.validate(clean) (https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/fields.py#L764). Changing it to value.validate(clean) works as expected, and I doubt this change will break anything as the value type is verified before this call.

There are two possible workaround:

  • Override the clean()
  • Redefine the field in the subclass

Both look kinda weird. I'm not sure if this is by-design, but since this validation method (overriding the validate()) is mentioned in the doc, I guess it should be expected for it to work this way.

Mongoengine 0.27.0 from PyPi, Python 3.8

Thanks for reporting, what you suggest makes sense. I'm working on a PR now