django-cms: Tree 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-treefails withtreebeard.exceptions.NodeAlreadySaved: Attempted to add a tree node that is already in the databasecms 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
About this issue
- Original URL
- State: open
- Created 7 years ago
- Comments: 25 (10 by maintainers)
@preinhart We use this at work. https://github.com/nephila/djangocms-multisite. This might solve your issues.
While I don’t work at the company where I had this issue anymore and I also know they stopped using django-cms due this problem (which was: every time they tried to change something it would delete everything, making updating the site impossible) and many other problems, as other people are reporting that they have the same issue I think reopening this issue might be helpful
Feel free to close it again