Skip to content

Proper ValidationError when trying to save a single doc as a list of EmbeddedDocuments #1464

@wojcikstefan

Description

@wojcikstefan
In [8]: class EmbeddedDoc(EmbeddedDocument):
   ...:     name = StringField()
   ...:

In [9]: class Doc(Document):
   ...:     docs = ListField(EmbeddedDocumentField(EmbeddedDoc))
   ...:

In [10]: Doc.objects.create(docs=[EmbeddedDoc(name='whatever')])  # works fine
Out[10]: <Doc: Doc object>

In [11]: Doc.objects.create(docs=EmbeddedDoc(name='whatever'))  # uh oh, assigning a single doc to a list?!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-226358097c9d> in <module>()
----> 1 Doc.objects.create(docs=EmbeddedDoc(name='whatever'))  # uh oh, assigning a single doc to a list?!

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/queryset/base.pyc in create(self, **kwargs)
    286         .. versionadded:: 0.4
    287         """
--> 288         return self._document(**kwargs).save()
    289
    290     def first(self):

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/base/document.pyc in __init__(self, *args, **values)
    113                         field = self._fields.get(key)
    114                         if field and not isinstance(field, FileField):
--> 115                             value = field.to_python(value)
    116                     setattr(self, key, value)
    117                 else:

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/base/fields.pyc in to_python(self, value)
    315             self.field._auto_dereference = self._auto_dereference
    316             value_dict = {key: self.field.to_python(item)
--> 317                           for key, item in value.items()}
    318         else:
    319             Document = _import_class('Document')

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/base/fields.pyc in <dictcomp>((key, item))
    315             self.field._auto_dereference = self._auto_dereference
    316             value_dict = {key: self.field.to_python(item)
--> 317                           for key, item in value.items()}
    318         else:
    319             Document = _import_class('Document')

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/fields.pyc in to_python(self, value)
    544     def to_python(self, value):
    545         if not isinstance(value, self.document_type):
--> 546             return self.document_type._from_son(value, _auto_dereference=self._auto_dereference)
    547         return value
    548

/Users/wojcikstefan/Repos/temp/mongoengine/mongoengine/base/document.pyc in _from_son(cls, son, _auto_dereference, only_fields, created)
    679
    680         if son and not isinstance(son, dict):
--> 681             raise ValueError("The source SON object needs to be of type 'dict'")
    682
    683         # Get the class name from the document, falling back to the given

ValueError: The source SON object needs to be of type 'dict'

ValueError: The source SON object needs to be of type 'dict' isn't very helpful when debugging this subtle issue.

With simple types it works as expected, raising a ValidationError with a clear message:

In [2]: class Doc(Document):
   ...:     lst = ListField(StringField())
   ...:

In [5]: Doc.objects.create(lst='1')
(...)
ValidationError: ValidationError (Doc:None) (Only lists and tuples may be used in a list field: ['lst'])

Thanks to #1460 for exposing it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions