MongoEngine / MongoEngine/mongoengine

Reference to Abstract Document generates an InvalidDocument

Open
#1,332 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4.3k
Forks
1.2k
Avg merge
4h 41m
Merged PRs (30d)
11

Description

Hi,

Regarding #1155, when I query on a object with a instance variable that has a ReferenceField to an abstract document and this field is already populated with one concrete subclass object.

I get an error when Mongoengine tries to run the method "from_son".
The error I get is the following

Invalid data to create a `User` instance.
notifications - type object 'UserNotifications' has no attribute 'id'  

Which makes sense because UserNotifications is indeed abstract. The reference field has the ObjectID of a EditorNotifications object.

Here's the entire stack trace in case it helps:

 Traceback (most recent call last):
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
        return self.dispatch(request, *args, **kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/utils/decorators.py", line 34, in _wrapper
        return bound_func(*args, **kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 22, in _wrapped_view
        return view_func(request, *args, **kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/utils/decorators.py", line 30, in bound_func
        return func.__get__(self, type(self))(*args2, **kwargs2)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/utils/decorators.py", line 34, in _wrapper
        return bound_func(*args, **kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/utils/decorators.py", line 110, in _wrapped_view
        response = view_func(request, *args, **kwargs)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/utils/decorators.py", line 30, in bound_func
        return func.__get__(self, type(self))(*args2, **kwargs2)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/views/generic/base.py", line 89, in dispatch
        return handler(request, *args, **kwargs)
      File "/Users/AfonsoGraca/Unbabel/unbabel/payment/views.py", line 68, in post
        if self.form.is_valid():
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/forms/forms.py", line 184, in is_valid
        return self.is_bound and not self.errors
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/forms/forms.py", line 176, in errors
        self.full_clean()
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/forms/forms.py", line 393, in full_clean
        self._clean_form()
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/django/forms/forms.py", line 417, in _clean_form
        cleaned_data = self.clean()
      File "/Users/AfonsoGraca/Unbabel/unbabel/payment/forms.py", line 22, in clean
        last_cash_out = self.editor.get_last_cash_out()
      File "/Users/AfonsoGraca/Unbabel/unbabel/users/mongo_models.py", line 1855, in get_last_cash_out
        return self.get_transactions().filter(type='Cash Out').first()
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 264, in first
        result = queryset[0]
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 161, in __getitem__
        return queryset._document._from_son(queryset._cursor[key],
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 1481, in _cursor
        self._cursor_obj = self._collection.find(self._query,
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 1515, in _query
        self._mongo_query = self._query_obj.to_query(self._document)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/visitor.py", line 89, in to_query
        query = self.accept(SimplificationVisitor())
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/visitor.py", line 139, in accept
        return visitor.visit_combination(self)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/visitor.py", line 39, in visit_combination
        return Q(**self._query_conjunction(queries))
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/queryset/visitor.py", line 59, in _query_conjunction
        combined_query.update(copy.deepcopy(query))
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 163, in deepcopy
        y = copier(x, memo)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 257, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 190, in deepcopy
        y = _reconstruct(x, rv, 1, memo)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 336, in _reconstruct
        y.__setstate__(state)
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/base/document.py", line 200, in __setstate__
        data["_data"] = self.__class__._from_son(data["_data"])._data
      File "/Users/AfonsoGraca/.virtualenvs/unbabel/lib/python2.7/site-packages/mongoengine/base/document.py", line 725, in _from_son
        raise InvalidDocumentError(msg)
    InvalidDocumentError: Invalid data to create a `User` instance.
    notifications - type object 'UserNotifications' has no attribute 'id'

Cheers

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the _from_son entry point named in the traceback and inspect how a ReferenceField targeting an abstract document resolves a stored ObjectID for a concrete subclass. Reproduce the case with an abstract UserNotifications reference populated by an EditorNotifications object; done means deserialization no longer raises InvalidDocumentError.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.