Skip to content

Instantly share code, notes, and snippets.

@benzkji
Created October 31, 2018 14:44
Show Gist options
  • Save benzkji/f9a42667939f74646dbf9d9c996884a8 to your computer and use it in GitHub Desktop.
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
Copy link

jrief commented Oct 31, 2018

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
Copy link
Author

benzkji commented Nov 1, 2018

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
Copy link
Author

benzkji commented Nov 1, 2018

...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