profile
viewpoint

Ask questionsTree broken after node delete/change/add

Summary

When the admin tries (for example) to delete a placeholder the delete fails with an error 500 saying MultipleObjectsReturned: get() returned more than one CMSPlugin -- it returned 36.

Traceback (most recent call last):
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 244, in inner
    return view(request, *args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/views/decorators/clickjacking.py", line 39, in wrapped_view
    resp = view_func(*args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/cms/admin/placeholderadmin.py", line 678, in delete_plugin
    plugin.delete()
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/cms/models/pluginmodel.py", line 483, in delete
    super(CMSPlugin, self).delete(*args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/treebeard/models.py", line 506, in delete
    self.__class__.objects.filter(pk=self.pk).delete()
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/treebeard/mp_tree.py", line 112, in delete
    parents[parentpath] = node.get_parent(True)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/treebeard/mp_tree.py", line 1072, in get_parent
    self.__class__).objects.get(path=parentpath)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/db/models/manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/marco/.virtualenvs/rollsite-2/lib/python2.7/site-packages/django/db/models/query.py", line 391, in get
    (self.model._meta.object_name, num)
MultipleObjectsReturned: get() returned more than one CMSPlugin -- it returned 35!

The error happens in MP_NodeQuerySet#delete (of django-treebeard) when the code tries to get a node parent with node.get_parent(True).

Looking at the database I can see that I have multiple plugins with the same path value (https://marcoacierno.space/xQzR3Qogo4.png) so I'm not sure but it might be the reason...

The "same path value for multiple plugins" also causes another bug in the delete code: when the deleted node is not a leaf node, most of the content in the website is deleted (because toremove.append(Q(path__startswith=node.path)) is used, which basically selects all my plugins in the database, even if in a different post)

Any suggestion how to debug the issue? Is normal that multiple plugins in the database have the same node path even when in different posts?

Commands run to fix/check what is happing:

  • cms fix-tree fails with treebeard.exceptions.NodeAlreadySaved: Attempted to add a tree node that is already in the database
  • cms check: https://pastebin.com/rYGWxmhq

The django-treebeard code:

# ok, got the minimal list of nodes to remove...
# we must also remove their children
# and update every parent node's numchild attribute
# LOTS OF FUN HERE!
for path, node in removed.items():
    parentpath = node._get_basepath(node.path, node.depth - 1)
    if parentpath:
        if parentpath not in parents:
            parents[parentpath] = node.get_parent(True)
        parent = parents[parentpath]
        if parent and parent.numchild > 0:
            parent.numchild -= 1
            parent.save()
    if node.is_leaf():
        toremove.append(Q(path=node.path))
    else:
        toremove.append(Q(path__startswith=node.path))

Expected behaviour

The plugin is correctly deleted and the site does not lose content.

Actual behaviour

When the admin tries to add/remove content there is a possibility that most of it gets deleted

Environment

  • Python version: 2.7
  • Django version: 1.9.5
  • django CMS version: 3.2.5
django-cms/django-cms

Answer questions greengoaxe

Hi @preinhart, we need the code where we can reproduce the error and then try to fix it. Thanks for your cooperation. greengoaxe

useful!

Related questions

No questions were found.
source:https://uonfu.com/
answerer
greengoaxe gitlab.com/greengo_axe Full stack Developer https://linkedin.com/in/verdefrancesco
Github User Rank List