Skip to content

Instantly share code, notes, and snippets.

@benzkji
Created October 31, 2018 14:44
Show Gist options
  • Select an option

  • Save benzkji/f9a42667939f74646dbf9d9c996884a8 to your computer and use it in GitHub Desktop.

Select an option

Save benzkji/f9a42667939f74646dbf9d9c996884a8 to your computer and use it in GitHub Desktop.
move first / last cms plugin context menu
# add to your normal cms_plugins.py whateverplugin
class DemoPlugin(CMSPluginBase):
model = Demo
...
def get_plugin_urls(self):
return [
url(r'^plugin_move_first/$', self.plugin_move_first, name='cmsplugin_move_first'),
url(r'^plugin_move_last/$', self.plugin_move_last, name='cmsplugin_move_last'),
]
@classmethod
def get_extra_global_plugin_menu_items(cls, request, plugin):
return [
PluginMenuItem(
_("Move to first position"),
reverse("admin:cmsplugin_move_first"),
data={'plugin_id': plugin.pk, 'csrfmiddlewaretoken': get_token(request)},
),
PluginMenuItem(
_("Move to last position"),
reverse("admin:cmsplugin_move_last"),
data={'plugin_id': plugin.pk, 'csrfmiddlewaretoken': get_token(request)},
)
]
def plugin_move_first(self, request):
return self._plugin_move_to(request, 'first')
def plugin_move_last(self, request):
return self._plugin_move_to(request, 'last')
def _plugin_move_to(self, request, position='first'):
if not request.user.is_staff:
return HttpResponseForbidden("not enough privileges")
if not 'plugin_id' in request.POST:
return HttpResponseBadRequest("plugin_id POST parameter missing.")
plugin = None
if 'plugin_id' in request.POST:
pk = request.POST['plugin_id']
try:
plugin = CMSPlugin.objects.get(pk=pk)
except CMSPlugin.DoesNotExist:
return HttpResponseBadRequest("plugin with id %s not found." % pk)
# do it!
base_qs = CMSPlugin.objects.filter(
placeholder=plugin.placeholder,
parent=plugin.parent,
)
old_position = plugin.position
if position == 'first':
new_position = 0
else:
new_position = base_qs.count() - 1
if new_position == old_position:
pass
if new_position > old_position:
update_qs = base_qs.filter(position__lte=new_position, position__gt=old_position)
update_qs.update(**{'position': F('position') - 1})
if new_position < old_position:
update_qs = base_qs.filter(position__gte=new_position, position__lt=old_position)
update_qs.update(**{'position': F('position') + 1})
plugin.position = new_position
plugin.save()
return HttpResponse('ok')
@jrief

jrief commented Oct 31, 2018

Copy link
Copy Markdown

when working with Treebeard, you should use their API to do "low-level" stuff. Presumably this method is your friend:
https://django-treebeard.readthedocs.io/en/latest/api.html#treebeard.models.Node.move

@benzkji

benzkji commented Nov 1, 2018

Copy link
Copy Markdown
Author

hm. the treebeard does the tree, but as far as I see, the cms uses only position, for sorting on each level?

https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py#L932
and here https://github.com/divio/django-cms/blob/develop/cms/utils/plugins.py#L304, as in the cms admin and utils methods for ordering?

@benzkji

benzkji commented Nov 1, 2018

Copy link
Copy Markdown
Author

...as mentioned, it already works...but sure, treebeard and position will not be in sync (but this happens all the time anyway, for example when sorting by hand with drag and drop, in structure mode...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment