django-cms / django-cms

The easy-to-use and developer-friendly enterprise CMS powered by Django
http://www.django-cms.org
BSD 3-Clause "New" or "Revised" License
9.97k stars 3.05k forks source link

[BUG] Moved plugins sometimes end at the wrong location #7898

Open jrief opened 1 month ago

jrief commented 1 month ago

Description

This is a weird problem and presumably difficult to reproduce.

I have a placeholder with hundreds of plugins with up to four nesting levels. If I open the the structure tree and move a plugin in one of the upper part, everything works fine. If however, I try to drag a plugin in the lower part of the structure tree, it is moved but after a short period it appears somewhere else.

https://github.com/django-cms/django-cms/assets/1132472/d1d3a544-b4e7-4df9-995b-595a7dcdb224

Steps to reproduce

I therefore added a breakpoint to see what's going on.

Then I dragged the penultimate plugin in the opened subtree to the first position. Here I checked the positions of the current plugins:

>>> [(p.position, p.id, p.plugin_type) for p in target_parent.get_descendants()]
[(161, 6289109, 'HeadingPlugin'), (162, 6289110, 'TextPlugin'), (163, 6289111, 'HeadingPlugin'), (164, 6289118, 'TextPlugin'), (165, 6289120, 'TextPlugin'), (178, 6289121, 'HeadingPlugin'), (179, 6289108, 'HeadingPlugin'), (182, 6289117, 'HeadingPlugin'), (183, 6289112, 'TextPlugin'), (184, 6289113, 'TextLinkPlugin'), (185, 6289114, 'TextLinkPlugin'), (186, 6289115, 'TextLinkPlugin'), (187, 6289122, 'TextPlugin'), (188, 6289123, 'TextLinkPlugin'), (189, 6289124, 'TextLinkPlugin'), (190, 6289116, 'TextLinkPlugin')]

Since the plugin is moved to the first position, I would expect request.POST['target_position'] to be 161. It however is 186. After dropping the plugin it remains where left, but after a short period it jumps to back to the penultimate position. This, because it has been moved to 186 instead of 161 and get_plugin_tree_as_json() then retrieves the complete subtree.

What's interesting is, that the position-field of the plugins in that subtree does not have a consecutive range, it jumps from 165 to 178 at the 6. position. Check the list comprehension shown above.

Additional information (CMS/Python/Django versions)

Django-CMS 4.1, latest commit on branch develop-4.

Do you want to help fix this issue?

fsbraun commented 1 month ago

Do you programmatically create plugins (e.g. with cascade)?

Here's a repo that includes a management command to fix the plugin tree: https://github.com/fsbraun/djangocms4-utilities

Try to fix with manage.py fixtree. At your own risk.

Duplicate of #7391

jrief commented 1 month ago

Do you programmatically create plugins (e.g. with cascade)?

Yes, through an import script. However, this script doesn't seem to be the culprit. I re-imported that content and ran ./manage.py checktree (from djangocms4-utilities) afterwards. There were no complains.

After running a modified version of manage.py fixtree the problem does not occur anymore.

fsbraun commented 1 month ago

The import script should be ok if it only uses cms.api. If you want I can have a look.

Other common situations include automated creation of, say, columns when creating a row.

fsbraun commented 1 month ago

Another potential source of the gaps could have been running the ./manage.py cms delete-orphaned-plugins management command. It was fixed in 4.1.1. Before that it left gaps when deleting ghost plugins: unsaved Text plugins.

I just realised when going through the changes of 4.1.1